Reference
OffsetArrays.OffsetArray
— TypeOffsetArray(A, indices...)
Return an AbstractArray
that shares element type and size with the first argument, but used the given indices
, which are checked for compatible size.
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: Colon()
(aka :
), UnitRange
(e.g, -1:2
), and CartesianIndices
.
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 this 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
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 can't be used interchangebly:
julia> OffsetArray(reshape(1:6, 2, 3), 0, -1:1)
ERROR: [...]
Example: origin
OffsetArrays.Origin
can be used to directly specify the origin of the output OffsetArray.
julia> a = [1 2; 3 4];
julia> OffsetArray(a, OffsetArrays.Origin(0, 1))
2×2 OffsetArray(::Array{Int64,2}, 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(::Array{Int64,2}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 2
3 4
OffsetArrays.OffsetVector
— TypeOffsetVector(v, index)
Type alias and convenience constructor for one-dimensional OffsetArray
s.
OffsetArrays.OffsetMatrix
— TypeOffsetMatrix(A, index1, index2)
Type alias and convenience constructor for two-dimensional OffsetArray
s.
OffsetArrays.Origin
— TypeOrigin(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(::Array{Int64,2}, 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(::Array{Int64,2}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 2
3 4
OffsetArrays.IdOffsetRange
— Typero = 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(-1:1)
julia> axes(ro, 1)
OffsetArrays.IdOffsetRange(-1:1)
julia> ro[-1]
-1
julia> ro[3]
ERROR: BoundsError: attempt to access 3-element UnitRange{Int64} at index [5]
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(9:11)
julia> axes(ro, 1) # 11:13 is indexed by 1:3, and the offset is also applied to the axes
OffsetArrays.IdOffsetRange(-1:1)
julia> ro[-1]
9
julia> ro[3]
ERROR: BoundsError: attempt to access 3-element UnitRange{Int64} at index [5]
Extended help
Construction/coercion preserves the (shifted) values of the input range, but may modify the indexes 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.
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.
OffsetArrays.no_offset_view
— Functionno_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(::Array{Int64,2}, 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 Array{Int64,2}:
-9 3 5
2 4 6
OffsetArrays.AxisConversionStyle
— TypeOffsetArrays.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