Skip to content

Commit

Permalink
Copy for CartesianIndices/LinearIndices need not materialize (Jul…
Browse files Browse the repository at this point in the history
…iaLang#53901)

Currently,
```julia
julia> C = CartesianIndices((1:2, 1:2))
CartesianIndices((1:2, 1:2))

julia> copy(C)
2×2 Matrix{CartesianIndex{2}}:
 CartesianIndex(1, 1)  CartesianIndex(1, 2)
 CartesianIndex(2, 1)  CartesianIndex(2, 2)
```
However, seeing that a `CartesianIndices` is equivalent to an n-D range,
there doesn't seem to be a need to materialize the result. This PR also
ensures that `copy(C)` returns the same type as `C`.

After this PR:
```julia
julia> C = CartesianIndices((1:2, 1:2))
CartesianIndices((1:2, 1:2))

julia> copy(C)
CartesianIndices((1:2, 1:2))
```
Also, a similar change for `LinearIndices` is added.
  • Loading branch information
jishnub authored Mar 31, 2024
1 parent 313f933 commit a3f710e
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 1 deletion.
1 change: 1 addition & 0 deletions base/indices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ function getindex(iter::LinearIndices, i::AbstractRange{<:Integer})
@boundscheck checkbounds(iter, i)
@inbounds isa(iter, LinearIndices{1}) ? iter.indices[1][i] : (first(iter):last(iter))[i]
end
copy(iter::LinearIndices) = iter
# More efficient iteration — predominantly for non-vector LinearIndices
# but one-dimensional LinearIndices must be special-cased to support OffsetArrays
iterate(iter::LinearIndices{1}, s...) = iterate(axes1(iter.indices[1]), s...)
Expand Down
4 changes: 3 additions & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
module IteratorsMD
import .Base: eltype, length, size, first, last, in, getindex, setindex!,
min, max, zero, oneunit, isless, eachindex,
convert, show, iterate, promote_rule, to_indices
convert, show, iterate, promote_rule, to_indices, copy

import .Base: +, -, *, (:)
import .Base: simd_outer_range, simd_inner_length, simd_index, setindex
Expand Down Expand Up @@ -476,6 +476,8 @@ module IteratorsMD
@inline in(i::CartesianIndex, r::CartesianIndices) = false
@inline in(i::CartesianIndex{N}, r::CartesianIndices{N}) where {N} = all(map(in, i.I, r.indices))

copy(iter::CartesianIndices) = iter

simd_outer_range(iter::CartesianIndices{0}) = iter
function simd_outer_range(iter::CartesianIndices)
CartesianIndices(tail(iter.indices))
Expand Down
7 changes: 7 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,13 @@ end
end
end

@testset "copy for LinearIndices/CartesianIndices" begin
C = CartesianIndices((1:2, 1:4))
@test copy(C) === C
L = LinearIndices((1:2, 1:4))
@test copy(L) === L
end

# token type on which to dispatch testing methods in order to avoid potential
# name conflicts elsewhere in the base test suite
mutable struct TestAbstractArray end
Expand Down

0 comments on commit a3f710e

Please sign in to comment.