# Reference

OffsetArrays.OffsetArrayType
OffsetArray(A, indices...)

Return an AbstractArray that shares element type and size with the first argument but uses the supplied indices to infer its axes. If all the indices are AbstractUnitRanges then these are directly used as the axis span along each dimension. Refer to the examples below for other permissible types.

Alternatively it's possible to specify the coordinates of one corner of the array and have the axes be computed automatically from the size of A. This constructor makes it convenient to shift to an arbitrary starting index along each axis, for example to a zero-based indexing scheme followed by arrays in languages such as C and Python. See Origin and the examples below for this usage.

Example: offsets

There are two types of indices: integers and ranges-like types.

Integers are recognized as offsets, where 0 means no offsets are applied:

julia> A = OffsetArray(reshape(1:6, 2, 3), -1, -2)
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1  3  5
2  4  6

julia> A[0, 1]
5

Examples of range-like types are: UnitRange (e.g, -1:2), CartesianIndices, and Colon() (or concisely :). A UnitRange specifies the axis span along one particular dimension, CartesianIndices specify the axis spans along multiple dimensions, and a Colon is a placeholder that specifies that the OffsetArray shares its axis with its parent along that dimension.

julia> OffsetArray(reshape(1:6, 2, 3), 0:1, -1:1)
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1  3  5
2  4  6

julia> OffsetArray(reshape(1:6, 2, 3), :, -1:1) # : as a placeholder to indicate that no offset is to be applied to the first dimension
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 1:2, -1:1) with eltype Int64 with indices 1:2×-1:1:
1  3  5
2  4  6

Use CartesianIndices to specify the coordinates of two diagonally opposite corners:

julia> OffsetArray(reshape(1:6, 2, 3), CartesianIndex(0, -1):CartesianIndex(1, 1))
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1  3  5
2  4  6

Integers and range-like types may not be combined in the same call:

julia> OffsetArray(reshape(1:6, 2, 3), 0, -1:1)
ERROR: [...]

Example: origin

OffsetArrays.Origin may be used to specify the origin of the OffsetArray. The term origin here refers to the corner with the lowest values of coordinates, such as the left edge for an AbstractVector, the bottom left corner for an AbstractMatrix and so on. The coordinates of the origin sets the starting index of the array along each dimension.

julia> a = [1 2; 3 4];

julia> OffsetArray(a, OffsetArrays.Origin(0, 1))
2×2 OffsetArray(::Matrix{Int64}, 0:1, 1:2) with eltype Int64 with indices 0:1×1:2:
1  2
3  4

julia> OffsetArray(a, OffsetArrays.Origin(0)) # set the origin to zero along each dimension
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1  2
3  4
source
OffsetArrays.OriginType
Origin(indices...)
Origin(origin::Tuple)
Origin(origin::CartesianIndex)

A helper type to construct OffsetArray with given origin.

The origin of an array is defined as the index of its first element, i.e., first.(axes(A)).

Example

julia> a = [1 2; 3 4];

julia> OffsetArray(a, OffsetArrays.Origin(0, 1))
2×2 OffsetArray(::Matrix{Int64}, 0:1, 1:2) with eltype Int64 with indices 0:1×1:2:
1  2
3  4

julia> OffsetArray(a, OffsetArrays.Origin(0)) # short notation for Origin(0, 0)
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1  2
3  4
source
OffsetArrays.IdOffsetRangeType
ro = IdOffsetRange(r::AbstractUnitRange, offset=0)

Construct an "identity offset range". Numerically, collect(ro) == collect(r) .+ offset, with the additional property that axes(ro, 1) = axes(r, 1) .+ offset. When r starts at 1, then ro[i] == i and even ro[ro] == ro, i.e., it's the "identity," which is the origin of the "Id" in IdOffsetRange.

Examples

The most common case is shifting a range that starts at 1 (either 1:n or Base.OneTo(n)):

julia> ro = OffsetArrays.IdOffsetRange(1:3, -2)
OffsetArrays.IdOffsetRange(values=-1:1, indices=-1:1)

julia> axes(ro, 1)
OffsetArrays.IdOffsetRange(values=-1:1, indices=-1:1)

julia> ro[-1]
-1

julia> ro[3]
ERROR: BoundsError: attempt to access 3-element OffsetArrays.OffsetArrays.IdOffsetRange{Int64, UnitRange{Int64}} with indices -1:1 at index [3]

If the range doesn't start at 1, the values may be different from the indices:

julia> ro = OffsetArrays.IdOffsetRange(11:13, -2)
OffsetArrays.IdOffsetRange(values=9:11, indices=-1:1)

julia> axes(ro, 1)     # 11:13 is indexed by 1:3, and the offset is also applied to the axes
OffsetArrays.IdOffsetRange(values=-1:1, indices=-1:1)

julia> ro[-1]
9

julia> ro[3]
ERROR: BoundsError: attempt to access 3-element OffsetArrays.OffsetArrays.IdOffsetRange{Int64, UnitRange{Int64}} with indices -1:1 at index [3]

Extended help

Construction/coercion preserves the (shifted) values of the input range, but may modify the indices if required by the specified types. For example,

r = OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}(3:4)

has r[1] == 3 and r[2] == 4, whereas

r = OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}(3:4)

has r[3] == 3 and r[4] == 4, and r[1] would throw a BoundsError. In this latter case, a shift in the axes was needed because Base.OneTo ranges must start with value 1.

Warning

In the future, conversion will preserve both the values and the indices, throwing an error when this is not achievable. For instance,

r = convert(OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}, 3:4)

has r[1] == 3 and r[2] == 4 and would satisfy r == 3:4, whereas

julia> convert(OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}, 3:4)    # future behavior, not present behavior
ERROR: ArgumentError: first element must be 1, got 3

where the error will arise because the result could not have the same axes as the input.

An important corollary is that typeof(r1)(r2) and oftype(r1, r2) will behave differently: the first coerces r2 to be of the type of r1, whereas the second converts. Developers are urged to future-proof their code by choosing the behavior appropriate for each usage.

source
OffsetArrays.no_offset_viewFunction
no_offset_view(A)

Return an AbstractArray that shares structure and underlying data with the argument, but uses 1-based indexing. May just return the argument when applicable. Not exported.

The default implementation uses OffsetArrays, but other types should use something more specific to remove a level of indirection when applicable.

julia> A = [1 3 5; 2 4 6];

julia> O = OffsetArray(A, 0:1, -1:1)
2×3 OffsetArray(::Matrix{Int64}, 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1  3  5
2  4  6

julia> OffsetArrays.no_offset_view(O)[1,1] = -9
-9

julia> A
2×3 Matrix{Int64}:
-9  3  5
2  4  6
source
OffsetArrays.AxisConversionStyleType
OffsetArrays.AxisConversionStyle(typeof(indices))

AxisConversionStyle declares if indices should be converted to a single AbstractUnitRange{Int} or to a Tuple{Vararg{AbstractUnitRange{Int}}} while flattening custom types into indices. This method is called after to_indices(A::Array, axes(A), indices) to provide further information in case to_indices does not return a Tuple of AbstractUnitRange{Int}.

Custom index types should extend AxisConversionStyle and return either OffsetArray.SingleRange(), which is the default, or OffsetArray.TupleOfRanges(). In the former case, the type T should define Base.convert(::Type{AbstractUnitRange{Int}}, ::T), whereas in the latter it should define Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, ::T).

An example of the latter is CartesianIndices, which is converted to a Tuple of AbstractUnitRange{Int} while flattening the indices.

Example

julia> struct NTupleOfUnitRanges{N}
x ::NTuple{N, UnitRange{Int}}
end

julia> Base.to_indices(A, inds, t::Tuple{NTupleOfUnitRanges{N}}) where {N} = t;

julia> OffsetArrays.AxisConversionStyle(::Type{NTupleOfUnitRanges{N}}) where {N} = OffsetArrays.TupleOfRanges();

julia> Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, t::NTupleOfUnitRanges) = t.x;

julia> a = zeros(3, 3);

julia> inds = NTupleOfUnitRanges((3:5, 2:4));

julia> oa = OffsetArray(a, inds);

julia> axes(oa, 1) == 3:5
true

julia> axes(oa, 2) == 2:4
true
source