@@ -172,6 +172,11 @@ module IteratorsMD
172172 Consequently these can be useful for writing algorithms that
173173 work in arbitrary dimensions.
174174
175+ CartesianRange(A::AbstractArray) -> R
176+
177+ As a convenience, constructing a CartesianRange from an array makes a
178+ range of its indices.
179+
175180 # Examples
176181 ```jldoctest
177182 julia> foreach(println, CartesianRange((2, 2, 2)))
@@ -183,7 +188,47 @@ module IteratorsMD
183188 CartesianIndex(2, 1, 2)
184189 CartesianIndex(1, 2, 2)
185190 CartesianIndex(2, 2, 2)
191+
192+ julia> CartesianRange(ones(2,3))
193+ 2×3 CartesianRange{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}:
194+ CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3)
195+ CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3)
186196 ```
197+
198+ ## Conversion between linear and cartesian indices
199+
200+ Linear index to cartesian index conversion exploits the fact that a
201+ `CartesianRange` is an `AbstractArray` and can be indexed linearly:
202+
203+ ```jldoctest subarray
204+ julia> cartesian = CartesianRange(1:3,1:2)
205+ 3×2 CartesianRange{2,Tuple{UnitRange{Int64},UnitRange{Int64}}}:
206+ CartesianIndex(1, 1) CartesianIndex(1, 2)
207+ CartesianIndex(2, 1) CartesianIndex(2, 2)
208+ CartesianIndex(3, 1) CartesianIndex(3, 2)
209+
210+ julia> cartesian[4]
211+ CartesianIndex(1, 2)
212+ ```
213+
214+ For cartesian to linear index conversion, [`eachindex`](@ref) returns a
215+ reshaped version of the linear indices when called on a `CartesianRange`:
216+
217+ ```jldoctest subarray
218+ julia> linear = eachindex(cartesian)
219+ 3×2 reshape(::Base.OneTo{Int64}, 3, 2) with eltype Int64:
220+ 1 4
221+ 2 5
222+ 3 6
223+
224+ julia> linear[1,2]
225+ 4
226+
227+ julia> linear[cartesian[4]]
228+ 4
229+ ```
230+
231+
187232 """
188233 struct CartesianRange{N,R<: NTuple{N,AbstractUnitRange{Int}} } <: AbstractArray{CartesianIndex{N},N}
189234 indices:: R
@@ -204,6 +249,8 @@ module IteratorsMD
204249 CartesianRange (inds:: NTuple{N,Union{<:Integer,AbstractUnitRange{<:Integer}}} ) where {N} =
205250 CartesianRange (map (i-> first (i): last (i), inds))
206251
252+ CartesianRange (A:: AbstractArray ) = CartesianRange (indices (A))
253+
207254 convert (:: Type{Tuple{}} , R:: CartesianRange{0} ) = ()
208255 convert (:: Type{NTuple{N,AbstractUnitRange{Int}}} , R:: CartesianRange{N} ) where {N} =
209256 R. indices
@@ -225,6 +272,7 @@ module IteratorsMD
225272 # AbstractArray implementation
226273 Base. IndexStyle (:: Type{CartesianRange{N,R}} ) where {N,R} = IndexCartesian ()
227274 @inline Base. getindex (iter:: CartesianRange{N,R} , I:: Vararg{Int, N} ) where {N,R} = CartesianIndex (first .(iter. indices) .- 1 .+ I)
275+ Base. eachindex (iter:: CartesianRange ) = reshape (linearindices (iter), size (iter))
228276
229277 ndims (R:: CartesianRange ) = ndims (typeof (R))
230278 ndims (:: Type{CartesianRange{N}} ) where {N} = N
0 commit comments