From a3f710e2a35402bb7f7f96f874e6c696dfc911da Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 31 Mar 2024 07:26:46 +0530 Subject: [PATCH] Copy for `CartesianIndices`/`LinearIndices` need not materialize (#53901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- base/indices.jl | 1 + base/multidimensional.jl | 4 +++- test/abstractarray.jl | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/indices.jl b/base/indices.jl index 9fadff1cdb5de..e629d2d6a03ff 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -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...) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 04274cd79c1aa..5fb2bf8cad582 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -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 @@ -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)) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 48451d43d79c4..a0a6ba6b2229a 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -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