You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use to_indices in the OffsetArray constructor (#157)
* use to_indices to simplify constructor dispatch
to_indices converts colons to ranges. This is followed by converting CartesianIndices to ranges.
* Fix indexing IdOffsetRange using offset ranges, ensuring that indexing is idempotent
* Define `firstindex` and `lastindex` for `IdOffsetRange`
* Check for consistency of dimensions in the `OffsetVector` and `OffsetMatrix` constructors.
While a wide variety of `AbstractUnitRange`s provided by `Base` may be used as indices to construct an `OffsetArray`, at times it might be convenient to define custom types. The `OffsetArray` constructor accepts any type that may be converted to an `AbstractUnitRange`. This proceeds through a two-step process. Let's assume that the constructor called is `OffsetArray(A, indstup)`, where `indstup` is a `Tuple` of indices.
150
+
151
+
1. At the first step, the constructor calls `to_indices(A, axes(A), indstup)` to lower `indstup` to a `Tuple` of `AbstractUnitRange`s. This step converts --- among other things --- `Colon`s to axis ranges. Custom types may extend `Base.to_indices(A, axes(A), indstup)` with the desired conversion of `indstup` to `Tuple{Vararg{AbstractUnitRange{Int}}}` if this is feasible.
152
+
153
+
2. At the second step, the result obtained from the previous step treated again to convert it to a `Tuple` of `AbstractUnitRange`s to handle cases where the first step doesn't achieve this. An additional customization option may be specified at this stage: a type may be converted either to a single `AbstractUnitRange{Int}`, or to a `Tuple` of them. A type might specify which of these two behaviours is desired by extending [`OffsetArrays.AxisConversionStyle`](@ref). An example of a type that is acted upon at this stage is `CartesianIndices`, which is converted to a `Tuple` of `AbstractUnitRange`s.
154
+
155
+
For example, here are a couple of custom type that facilitate zero-based indexing:
In this example we had to define the action of `to_indices` as the type `ZeroBasedIndexing` did not have a familiar hierarchy. Things are even simpler if we subtype `AbstractUnitRange`, in which case we need to define `first` and `length` for the custom range to be able to use it as an axis:
171
+
172
+
```jldoctest; setup = :(using OffsetArrays)
173
+
julia> struct ZeroTo <: AbstractUnitRange{Int}
174
+
n :: Int
175
+
ZeroTo(n) = new(n < 0 ? -1 : n)
176
+
end
177
+
178
+
julia> Base.first(::ZeroTo) = 0
179
+
180
+
julia> Base.length(r::ZeroTo) = r.n + 1
181
+
182
+
julia> oa = OffsetArray(zeros(2,2), ZeroTo(1), ZeroTo(1));
# Performance gain by wrapping the error in a function: see https://github.com/JuliaLang/julia/issues/37558
165
+
throw_dimerr(lA, lI) =throw(DimensionMismatch("supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices"))
166
+
lA =size(A)
140
167
lI =map(length, inds)
141
-
lA == lI ||throw(DimensionMismatch("supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices"))
142
-
$FT(A, map(_offset, axparent, inds))
143
-
end
144
-
# lower CartesianIndices and Colon
145
-
@evalfunction$FT(A::AbstractArray{T}, inds::NTuple{N, OffsetAxis}) where {T, N}
0 commit comments