Skip to content

Commit b74ae55

Browse files
authored
Specialize copy and getindex with Colons (#207)
* forward colon * linear indexing with a single colon * remove comment
1 parent 8b1a809 commit b74ae55

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

Project.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
77

88
[compat]
99
Adapt = "2, 3"
10+
Aqua = "0.5"
11+
CatIndices = "0.2"
12+
Documenter = "0.26"
13+
EllipsisNotation = "1"
14+
FillArrays = "0.11"
15+
StaticArrays = "1"
1016
julia = "0.7, 1"
1117

1218
[extras]
@@ -15,9 +21,10 @@ CatIndices = "aafaddc9-749c-510e-ac4f-586e18779b91"
1521
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
1622
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
1723
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
24+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1825
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1926
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2027
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2128

2229
[targets]
23-
test = ["Aqua", "CatIndices", "DelimitedFiles", "Documenter", "Test", "LinearAlgebra", "EllipsisNotation", "StaticArrays"]
30+
test = ["Aqua", "CatIndices", "DelimitedFiles", "Documenter", "Test", "LinearAlgebra", "EllipsisNotation", "StaticArrays", "FillArrays"]

src/OffsetArrays.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,23 @@ Base.falses(inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {N} =
320320
# and one obtains the result below.
321321
parentindex(r::IdOffsetRange, i) = i - r.offset
322322

323-
@inline function Base.getindex(A::OffsetArray{T,N}, I::Vararg{Int,N}) where {T,N}
323+
@propagate_inbounds Base.getindex(A::OffsetArray{<:Any,0}) = A.parent[]
324+
325+
@inline function Base.getindex(A::OffsetArray{<:Any,N}, I::Vararg{Int,N}) where N
324326
@boundscheck checkbounds(A, I...)
325327
J = map(parentindex, axes(A), I)
326328
@inbounds parent(A)[J...]
327329
end
328330

331+
@propagate_inbounds Base.getindex(A::OffsetArray{<:Any,N}, c::Vararg{Colon,N}) where N =
332+
OffsetArray(A.parent[c...], A.offsets)
333+
334+
# With one Colon we use linear indexing.
335+
# In this case we may forward the index to the parent, as the information about the axes is lost
336+
# The exception to this is with OffsetVectors where the axis information is preserved,
337+
# but that case is handled by getindex(::OffsetArray{<:Any,N}, ::Vararg{Colon,N})
338+
@propagate_inbounds Base.getindex(A::OffsetArray, c::Colon) = A.parent[:]
339+
329340
@inline function Base.getindex(A::OffsetVector, i::Int)
330341
@boundscheck checkbounds(A, i)
331342
@inbounds parent(A)[parentindex(Base.axes1(A), i)]
@@ -350,6 +361,7 @@ end
350361
end
351362

352363
Base.in(x, A::OffsetArray) = in(x, parent(A))
364+
Base.copy(A::OffsetArray) = OffsetArray(copy(A.parent), A.offsets)
353365

354366
Base.strides(A::OffsetArray) = strides(parent(A))
355367
Base.elsize(::Type{OffsetArray{T,N,A}}) where {T,N,A} = Base.elsize(A)
@@ -394,9 +406,6 @@ for OR in [:IIUR, :IdOffsetRange]
394406
end
395407
end
396408

397-
# This is technically breaking, so it might be incorporated in the next major release
398-
# Base.getindex(a::OffsetRange, ::Colon) = OffsetArray(a.parent[:], a.offsets)
399-
400409
# mapreduce is faster with an IdOffsetRange than with an OffsetUnitRange
401410
# We therefore convert OffsetUnitRanges to IdOffsetRanges with the same values and axes
402411
function Base.mapreduce(f, op, As::OffsetUnitRange{<:Integer}...; kw...)

test/runtests.jl

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using CatIndices: BidirectionalVector
88
using EllipsisNotation
99
using Adapt
1010
using StaticArrays
11+
using FillArrays
1112

1213
DocMeta.setdocmeta!(OffsetArrays, :DocTestSetup, :(using OffsetArrays); recursive=true)
1314

@@ -887,9 +888,37 @@ end
887888
@test A[1, [4,3]] == S[1, [4,3]] == [4,2]
888889
@test A[:, :] == S[:, :] == A
889890

891+
# Indexing a nD OffsetArray with n colons preserves the type
890892
r1 = OffsetArray(IdentityUnitRange(100:1000), 3)
891-
r2 = r1[:]
892-
@test r2 == r1
893+
@test r1[:] === r1
894+
895+
# In general with more colons than dimensions,
896+
# the type might not be preserved but the values and the leading axes should be
897+
r2 = r1[:,:]
898+
@test axes(r2, 1) == axes(r1, 1)
899+
@test same_value(r1, r2)
900+
901+
s = @SVector[i for i in 1:3]
902+
so = OffsetArray(s, 3)
903+
@test so[:] === so
904+
905+
a = Ones(3, 2, 1)
906+
ao = OffsetArray(a, axes(a))
907+
@test ao[:,:,:] === ao
908+
@test same_value(ao[:], ao)
909+
@test same_value(ao[:,:], ao)
910+
911+
# Indexing an nD OffsetArray with one Colon preserves only the values.
912+
# This uses linear indexing
913+
a = ones(2:3, 2:3)
914+
b = a[:]
915+
@test same_value(a, b)
916+
917+
vals = (1,2,3,4,5,6,7,8)
918+
s = SArray{Tuple{2,2,2},Int,3,8}(vals)
919+
so = OffsetArray(s, axes(s));
920+
so2 = so[:]
921+
@test same_value(so2, s)
893922

894923
for r1 in Any[
895924
# AbstractArrays

0 commit comments

Comments
 (0)