Skip to content

Commit fb666b1

Browse files
authored
Merge pull request #20974 from JuliaLang/teh/new_cartrange
[1.0-dev] Store indices in CartesianRange
2 parents 1e95e1d + 2e0601e commit fb666b1

File tree

7 files changed

+95
-63
lines changed

7 files changed

+95
-63
lines changed

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ This section lists changes that do not have deprecation warnings.
4949
* The format for a `ClusterManager` specifying the cookie on the command line is now
5050
`--worker=<cookie>`. `--worker <cookie>` will not work as it is now an optional argument.
5151

52+
* The representation of `CartesianRange` has changed to a
53+
tuple-of-AbstractUnitRanges; the `start` and `stop` fields are no
54+
longer present. Use `first(R)` and `last(R)` to obtain
55+
start/stop. ([#20974])
56+
5257
Library improvements
5358
--------------------
5459

@@ -920,6 +925,7 @@ Command-line option changes
920925
[#20609]: https://github.com/JuliaLang/julia/issues/20609
921926
[#20889]: https://github.com/JuliaLang/julia/issues/20889
922927
[#20952]: https://github.com/JuliaLang/julia/issues/20952
928+
[#20974]: https://github.com/JuliaLang/julia/issues/20974
923929
[#21183]: https://github.com/JuliaLang/julia/issues/21183
924930
[#21359]: https://github.com/JuliaLang/julia/issues/21359
925931
[#21692]: https://github.com/JuliaLang/julia/issues/21692

base/deprecated.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,7 +1549,14 @@ end
15491549
@deprecate read(s::IO, t::Type, d1::Integer, dims::Integer...) read!(s, Array{t}(convert(Tuple{Vararg{Int}},tuple(d1,dims...))))
15501550
@deprecate read(s::IO, t::Type, dims::Dims) read!(s, Array{t}(dims))
15511551

1552+
function CartesianRange{N}(start::CartesianIndex{N}, stop::CartesianIndex{N})
1553+
inds = map((f,l)->f:l, start.I, stop.I)
1554+
depwarn("the internal representation of CartesianRange has changed, use CartesianRange($inds) (or other more approriate AbstractUnitRange type) instead.", :CartesianRange)
1555+
CartesianRange(inds)
1556+
end
1557+
15521558
# END 0.7 deprecations
15531559

15541560
# BEGIN 1.0 deprecations
1561+
15551562
# END 1.0 deprecations

base/multidimensional.jl

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
### Multidimensional iterators
44
module IteratorsMD
5-
import Base: eltype, length, size, start, done, next, last, in, getindex,
5+
import Base: eltype, length, size, start, done, next, first, last, in, getindex,
66
setindex!, IndexStyle, min, max, zero, one, isless, eachindex,
77
ndims, iteratorsize, convert
88

@@ -135,7 +135,6 @@ module IteratorsMD
135135

136136
# Iteration
137137
"""
138-
CartesianRange(Istart::CartesianIndex, Istop::CartesianIndex) -> R
139138
CartesianRange(sz::Dims) -> R
140139
CartesianRange(istart:istop, jstart:jstop, ...) -> R
141140
@@ -166,28 +165,46 @@ module IteratorsMD
166165
CartesianIndex{3}((2, 2, 2))
167166
```
168167
"""
169-
struct CartesianRange{I<:CartesianIndex}
170-
start::I
171-
stop::I
168+
struct CartesianRange{N,R<:NTuple{N,AbstractUnitRange{Int}}}
169+
indices::R
172170
end
173171

174-
CartesianRange(index::CartesianIndex) = CartesianRange(one(index), index)
175-
CartesianRange(::Tuple{}) = CartesianRange{CartesianIndex{0}}(CartesianIndex{0}(()),CartesianIndex{0}(()))
176-
CartesianRange(sz::NTuple{N,Int}) where {N} = CartesianRange(CartesianIndex(sz))
177-
CartesianRange(rngs::NTuple{N,Union{Integer,AbstractUnitRange}}) where {N} =
178-
CartesianRange(CartesianIndex(map(first, rngs)), CartesianIndex(map(last, rngs)))
179-
180-
convert(::Type{NTuple{N,UnitRange{Int}}}, R::CartesianRange{CartesianIndex{N}}) where {N} =
181-
map((f,l)->f:l, first(R).I, last(R).I)
182-
convert(::Type{NTuple{N,UnitRange}}, R::CartesianRange) where {N} =
183-
convert(NTuple{N,UnitRange{Int}}, R)
184-
convert(::Type{Tuple{Vararg{UnitRange{Int}}}}, R::CartesianRange{CartesianIndex{N}}) where {N} =
172+
CartesianRange(::Tuple{}) = CartesianRange{0,typeof(())}(())
173+
CartesianRange(inds::NTuple{N,AbstractUnitRange{Int}}) where {N} =
174+
CartesianRange{N,typeof(inds)}(inds)
175+
CartesianRange(inds::Vararg{AbstractUnitRange{Int},N}) where {N} =
176+
CartesianRange(inds)
177+
CartesianRange(inds::NTuple{N,AbstractUnitRange{<:Integer}}) where {N} =
178+
CartesianRange(map(r->convert(AbstractUnitRange{Int}, r), inds))
179+
CartesianRange(inds::Vararg{AbstractUnitRange{<:Integer},N}) where {N} =
180+
CartesianRange(inds)
181+
182+
CartesianRange(index::CartesianIndex) = CartesianRange(index.I)
183+
CartesianRange(sz::NTuple{N,<:Integer}) where {N} = CartesianRange(map(Base.OneTo, sz))
184+
CartesianRange(inds::NTuple{N,Union{<:Integer,AbstractUnitRange{<:Integer}}}) where {N} =
185+
CartesianRange(map(i->first(i):last(i), inds))
186+
187+
convert(::Type{Tuple{}}, R::CartesianRange{0}) = ()
188+
convert(::Type{NTuple{N,AbstractUnitRange{Int}}}, R::CartesianRange{N}) where {N} =
189+
R.indices
190+
convert(::Type{NTuple{N,AbstractUnitRange}}, R::CartesianRange{N}) where {N} =
191+
convert(NTuple{N,AbstractUnitRange{Int}}, R)
192+
convert(::Type{NTuple{N,UnitRange{Int}}}, R::CartesianRange{N}) where {N} =
193+
UnitRange{Int}.(convert(NTuple{N,AbstractUnitRange}, R))
194+
convert(::Type{NTuple{N,UnitRange}}, R::CartesianRange{N}) where {N} =
195+
UnitRange.(convert(NTuple{N,AbstractUnitRange}, R))
196+
convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, R::CartesianRange{N}) where {N} =
197+
convert(NTuple{N,AbstractUnitRange{Int}}, R)
198+
convert(::Type{Tuple{Vararg{AbstractUnitRange}}}, R::CartesianRange) =
199+
convert(Tuple{Vararg{AbstractUnitRange{Int}}}, R)
200+
convert(::Type{Tuple{Vararg{UnitRange{Int}}}}, R::CartesianRange{N}) where {N} =
185201
convert(NTuple{N,UnitRange{Int}}, R)
186202
convert(::Type{Tuple{Vararg{UnitRange}}}, R::CartesianRange) =
187203
convert(Tuple{Vararg{UnitRange{Int}}}, R)
188204

189-
ndims(R::CartesianRange) = length(R.start)
190-
ndims(::Type{CartesianRange{I}}) where {I<:CartesianIndex} = length(I)
205+
ndims(R::CartesianRange) = ndims(typeof(R))
206+
ndims(::Type{CartesianRange{N}}) where {N} = N
207+
ndims(::Type{CartesianRange{N,TT}}) where {N,TT} = N
191208

192209
eachindex(::IndexCartesian, A::AbstractArray) = CartesianRange(indices(A))
193210

@@ -201,17 +218,20 @@ module IteratorsMD
201218
@inline maxt(a::Tuple, b::Tuple{}) = a
202219
@inline maxt(a::Tuple, b::Tuple) = (max(a[1], b[1]), maxt(tail(a), tail(b))...)
203220

204-
eltype(::Type{CartesianRange{I}}) where {I} = I
221+
eltype(R::CartesianRange) = eltype(typeof(R))
222+
eltype(::Type{CartesianRange{N}}) where {N} = CartesianIndex{N}
223+
eltype(::Type{CartesianRange{N,TT}}) where {N,TT} = CartesianIndex{N}
205224
iteratorsize(::Type{<:CartesianRange}) = Base.HasShape()
206225

207-
@inline function start(iter::CartesianRange{<:CartesianIndex})
208-
if any(map(>, iter.start.I, iter.stop.I))
209-
return iter.stop+1
226+
@inline function start(iter::CartesianRange)
227+
iterfirst, iterlast = first(iter), last(iter)
228+
if any(map(>, iterfirst.I, iterlast.I))
229+
return iterlast+1
210230
end
211-
iter.start
231+
iterfirst
212232
end
213-
@inline function next(iter::CartesianRange{I}, state) where I<:CartesianIndex
214-
state, I(inc(state.I, iter.start.I, iter.stop.I))
233+
@inline function next(iter::CartesianRange, state)
234+
state, CartesianIndex(inc(state.I, first(iter).I, last(iter).I))
215235
end
216236
# increment & carry
217237
@inline inc(::Tuple{}, ::Tuple{}, ::Tuple{}) = ()
@@ -223,39 +243,38 @@ module IteratorsMD
223243
newtail = inc(tail(state), tail(start), tail(stop))
224244
(start[1], newtail...)
225245
end
226-
@inline done(iter::CartesianRange{<:CartesianIndex}, state) = state.I[end] > iter.stop.I[end]
246+
@inline done(iter::CartesianRange, state) = state.I[end] > last(iter.indices[end])
227247

228248
# 0-d cartesian ranges are special-cased to iterate once and only once
229-
start(iter::CartesianRange{<:CartesianIndex{0}}) = false
230-
next(iter::CartesianRange{<:CartesianIndex{0}}, state) = iter.start, true
231-
done(iter::CartesianRange{<:CartesianIndex{0}}, state) = state
249+
start(iter::CartesianRange{0}) = false
250+
next(iter::CartesianRange{0}, state) = CartesianIndex(), true
251+
done(iter::CartesianRange{0}, state) = state
232252

233-
size(iter::CartesianRange{<:CartesianIndex}) = map(dimlength, iter.start.I, iter.stop.I)
253+
size(iter::CartesianRange) = map(dimlength, first(iter).I, last(iter).I)
234254
dimlength(start, stop) = stop-start+1
235255

236256
length(iter::CartesianRange) = prod(size(iter))
237257

238-
last(iter::CartesianRange) = iter.stop
258+
first(iter::CartesianRange) = CartesianIndex(map(first, iter.indices))
259+
last(iter::CartesianRange) = CartesianIndex(map(last, iter.indices))
239260

240-
@inline function in(i::I, r::CartesianRange{I}) where I<:CartesianIndex
241-
_in(true, i.I, r.start.I, r.stop.I)
261+
@inline function in(i::CartesianIndex{N}, r::CartesianRange{N}) where {N}
262+
_in(true, i.I, first(r).I, last(r).I)
242263
end
243264
_in(b, ::Tuple{}, ::Tuple{}, ::Tuple{}) = b
244265
@inline _in(b, i, start, stop) = _in(b & (start[1] <= i[1] <= stop[1]), tail(i), tail(start), tail(stop))
245266

246-
simd_outer_range(iter::CartesianRange{CartesianIndex{0}}) = iter
267+
simd_outer_range(iter::CartesianRange{0}) = iter
247268
function simd_outer_range(iter::CartesianRange)
248-
start = CartesianIndex(tail(iter.start.I))
249-
stop = CartesianIndex(tail(iter.stop.I))
250-
CartesianRange(start, stop)
269+
CartesianRange(tail(iter.indices))
251270
end
252271

253-
simd_inner_length(iter::CartesianRange{<:CartesianIndex{0}}, ::CartesianIndex) = 1
254-
simd_inner_length(iter::CartesianRange, I::CartesianIndex) = iter.stop[1]-iter.start[1]+1
272+
simd_inner_length(iter::CartesianRange{0}, ::CartesianIndex) = 1
273+
simd_inner_length(iter::CartesianRange, I::CartesianIndex) = length(iter.indices[1])
255274

256-
simd_index(iter::CartesianRange{<:CartesianIndex{0}}, ::CartesianIndex, I1::Int) = iter.start
275+
simd_index(iter::CartesianRange{0}, ::CartesianIndex, I1::Int) = first(iter)
257276
@inline function simd_index(iter::CartesianRange, Ilast::CartesianIndex, I1::Int)
258-
CartesianIndex((I1+iter.start[1], Ilast.I...))
277+
CartesianIndex((I1+first(iter.indices[1]), Ilast.I...))
259278
end
260279

261280
# Split out the first N elements of a tuple
@@ -859,23 +878,23 @@ function copy!(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) where {T,N}
859878
end
860879

861880
@generated function copy!(dest::AbstractArray{T1,N},
862-
Rdest::CartesianRange{CartesianIndex{N}},
881+
Rdest::CartesianRange{N},
863882
src::AbstractArray{T2,N},
864-
Rsrc::CartesianRange{CartesianIndex{N}}) where {T1,T2,N}
883+
Rsrc::CartesianRange{N}) where {T1,T2,N}
865884
quote
866885
isempty(Rdest) && return dest
867886
if size(Rdest) != size(Rsrc)
868887
throw(ArgumentError("source and destination must have same size (got $(size(Rsrc)) and $(size(Rdest)))"))
869888
end
870-
@boundscheck checkbounds(dest, Rdest.start)
871-
@boundscheck checkbounds(dest, Rdest.stop)
872-
@boundscheck checkbounds(src, Rsrc.start)
873-
@boundscheck checkbounds(src, Rsrc.stop)
874-
ΔI = Rdest.start - Rsrc.start
889+
@boundscheck checkbounds(dest, first(Rdest))
890+
@boundscheck checkbounds(dest, last(Rdest))
891+
@boundscheck checkbounds(src, first(Rsrc))
892+
@boundscheck checkbounds(src, last(Rsrc))
893+
ΔI = first(Rdest) - first(Rsrc)
875894
# TODO: restore when #9080 is fixed
876895
# for I in Rsrc
877896
# @inbounds dest[I+ΔI] = src[I]
878-
@nloops $N i (n->Rsrc.start[n]:Rsrc.stop[n]) begin
897+
@nloops $N i (n->Rsrc.indices[n]) begin
879898
@inbounds @nref($N,dest,n->i_n+ΔI[n]) = @nref($N,src,i)
880899
end
881900
dest

base/permuteddimsarray.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ function _copy!(P::PermutedDimsArray{T,N,perm}, src) where {T,N,perm}
157157
return P
158158
end
159159

160-
@noinline function _permutedims!(P::PermutedDimsArray, src, R1::CartesianRange{CartesianIndex{0}}, R2, R3, ds, dp)
160+
@noinline function _permutedims!(P::PermutedDimsArray, src, R1::CartesianRange{0}, R2, R3, ds, dp)
161161
ip, is = indices(src, dp), indices(src, ds)
162162
for jo in first(ip):8:last(ip), io in first(is):8:last(is)
163163
for I3 in R3, I2 in R2

base/range.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,10 @@ promote_rule(::Type{UnitRange{T1}}, ::Type{UR}) where {T1,UR<:AbstractUnitRange}
778778
convert(::Type{UnitRange{T}}, r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r))
779779
convert(::Type{UnitRange}, r::AbstractUnitRange) = UnitRange(first(r), last(r))
780780

781+
convert(::Type{AbstractUnitRange{T}}, r::AbstractUnitRange{T}) where {T} = r
782+
convert(::Type{AbstractUnitRange{T}}, r::UnitRange) where {T} = convert(UnitRange{T}, r)
783+
convert(::Type{AbstractUnitRange{T}}, r::OneTo) where {T} = convert(OneTo{T}, r)
784+
781785
promote_rule(::Type{StepRange{T1a,T1b}},::Type{StepRange{T2a,T2b}}) where {T1a,T1b,T2a,T2b} =
782786
StepRange{promote_type(T1a,T2a),promote_type(T1b,T2b)}
783787
convert(::Type{StepRange{T1,T2}}, r::StepRange{T1,T2}) where {T1,T2} = r

test/arrayops.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,9 +1544,10 @@ end
15441544
@test a[1,2] == 7
15451545
@test 2*CartesianIndex{3}(1,2,3) == CartesianIndex{3}(2,4,6)
15461546

1547-
R = CartesianRange(CartesianIndex{2}(2,3),CartesianIndex{2}(5,5))
1547+
R = CartesianRange(2:5, 3:5)
15481548
@test eltype(R) <: CartesianIndex{2}
15491549
@test eltype(typeof(R)) <: CartesianIndex{2}
1550+
@test eltype(CartesianRange{2}) <: CartesianIndex{2}
15501551
indexes = collect(R)
15511552
@test indexes[1] == CartesianIndex{2}(2,3)
15521553
@test indexes[2] == CartesianIndex{2}(3,3)
@@ -1568,8 +1569,8 @@ end
15681569
@test @inferred(convert(NTuple{2,UnitRange}, R)) === (2:5, 3:5)
15691570
@test @inferred(convert(Tuple{Vararg{UnitRange}}, R)) === (2:5, 3:5)
15701571

1571-
@test CartesianRange((3:5,-7:7)) == CartesianRange(CartesianIndex{2}(3,-7),CartesianIndex{2}(5,7))
1572-
@test CartesianRange((3,-7:7)) == CartesianRange(CartesianIndex{2}(3,-7),CartesianIndex{2}(3,7))
1572+
@test CartesianRange((3:5,-7:7)) == CartesianRange(3:5,-7:7)
1573+
@test CartesianRange((3,-7:7)) == CartesianRange(3:3,-7:7)
15731574
end
15741575

15751576
# All we really care about is that we have an optimized

test/simdloop.jl

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,28 +101,23 @@ function simd_cartesian_range!(indexes, crng)
101101
indexes
102102
end
103103

104-
crng = CartesianRange(CartesianIndex{4}(2,0,1,3),
105-
CartesianIndex{4}(4,1,1,5))
104+
crng = CartesianRange(2:4, 0:1, 1:1, 3:5)
106105
indexes = simd_cartesian_range!(Array{eltype(crng)}(0), crng)
107106
@test indexes == vec(collect(crng))
108107

109-
crng = CartesianRange(CartesianIndex{2}(-1,1),
110-
CartesianIndex{2}(1,3))
108+
crng = CartesianRange(-1:1, 1:3)
111109
indexes = simd_cartesian_range!(Array{eltype(crng)}(0), crng)
112110
@test indexes == vec(collect(crng))
113111

114-
crng = CartesianRange(CartesianIndex{2}(-1,1),
115-
CartesianIndex{2}(-1,3))
112+
crng = CartesianRange(-1:-1, 1:3)
116113
indexes = simd_cartesian_range!(Array{eltype(crng)}(0), crng)
117114
@test indexes == vec(collect(crng))
118115

119-
crng = CartesianRange(CartesianIndex{1}(2),
120-
CartesianIndex{1}(4))
116+
crng = CartesianRange(2:4)
121117
indexes = simd_cartesian_range!(Array{eltype(crng)}(0), crng)
122118
@test indexes == collect(crng)
123119

124-
crng = CartesianRange(CartesianIndex{0}(),
125-
CartesianIndex{0}())
120+
crng = CartesianRange()
126121
indexes = simd_cartesian_range!(Array{eltype(crng)}(0), crng)
127122
@test indexes == vec(collect(crng))
128123

0 commit comments

Comments
 (0)