Skip to content

Commit 12b733b

Browse files
authored
Merge pull request #10 from mcabbott/getindex
2 parents fe49430 + a4d79af commit 12b733b

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed

src/CircularArrays.jl

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export CircularArray, CircularVector
1010
1111
`N`-dimensional array backed by an `AbstractArray{T, N}` of type `A` with fixed size and circular indexing.
1212
13-
array[index] == array[mod1(index, size)]
13+
array[index...] == array[mod1.(index, size)...]
1414
"""
1515
struct CircularArray{T, N, A} <: AbstractArray{T, N}
1616
data::A
@@ -23,24 +23,33 @@ end
2323
One-dimensional array backed by an `AbstractArray{T, 1}` of type `A` with fixed size and circular indexing.
2424
Alias for [`CircularArray{T,1,A}`](@ref).
2525
26-
array[index] == array[mod1(index, size)]
26+
array[index] == array[mod1(index, length)]
2727
"""
2828
const CircularVector{T} = CircularArray{T, 1}
2929

30-
@inline clamp_bounds(arr::CircularArray, I::Tuple{Vararg{Int}})::AbstractArray{Int, 1} = map(Base.splat(mod), zip(I, axes(arr.data)))
31-
3230
CircularArray(data::AbstractArray{T,N}) where {T,N} = CircularArray{T,N}(data)
3331
CircularArray{T}(data::AbstractArray{T,N}) where {T,N} = CircularArray{T,N}(data)
3432
CircularArray(def::T, size) where T = CircularArray(fill(def, size))
3533

36-
@inline Base.getindex(arr::CircularArray, i::Int) = @inbounds getindex(arr.data, mod(i, Base.axes1(arr.data)))
37-
@inline Base.setindex!(arr::CircularArray, v, i::Int) = @inbounds setindex!(arr.data, v, mod(i, Base.axes1(arr.data)))
38-
@inline Base.getindex(arr::CircularArray, I::Vararg{Int}) = @inbounds getindex(arr.data, clamp_bounds(arr, I)...)
39-
@inline Base.setindex!(arr::CircularArray, v, I::Vararg{Int}) = @inbounds setindex!(arr.data, v, clamp_bounds(arr, I)...)
34+
@inline Base.getindex(arr::CircularArray, i::Int) =
35+
@inbounds getindex(arr.data, mod1(i, length(arr.data)))
36+
@inline Base.getindex(arr::CircularArray{T,N}, I::Vararg{<:Int,N}) where {T,N} =
37+
@inbounds getindex(arr.data, map(mod, I, axes(arr.data))...)
38+
39+
@inline Base.setindex!(arr::CircularArray, v, i::Int) =
40+
@inbounds setindex!(arr.data, v, mod1(i, length(arr.data)))
41+
@inline Base.setindex!(arr::CircularArray{T,N}, v, I::Vararg{<:Int,N}) where {T,N} =
42+
@inbounds setindex!(arr.data, v, map(mod, I, axes(arr.data))...)
43+
4044
@inline Base.size(arr::CircularArray) = size(arr.data)
4145
@inline Base.axes(arr::CircularArray) = axes(arr.data)
46+
Base.parent(arr::CircularArray) = arr.data
4247

43-
@inline Base.checkbounds(::CircularArray, _...) = nothing
48+
@inline function Base.checkbounds(arr::CircularArray, I...)
49+
J = Base.to_indices(arr, I)
50+
length(J) == 1 || length(J) >= ndims(arr) || throw(BoundsError(arr, I))
51+
nothing
52+
end
4453

4554
@inline _similar(arr::CircularArray, ::Type{T}, dims) where T = CircularArray(similar(arr.data,T,dims))
4655
@inline Base.similar(arr::CircularArray, ::Type{T}, dims::Tuple{Base.DimOrInd, Vararg{Base.DimOrInd}}) where T = _similar(arr,T,dims)
@@ -50,6 +59,14 @@ CircularArray(def::T, size) where T = CircularArray(fill(def, size))
5059
CircularVector(data::AbstractArray{T, 1}) where T = CircularVector{T}(data)
5160
CircularVector(def::T, size::Int) where T = CircularVector{T}(fill(def, size))
5261

62+
Base.IndexStyle(::Type{CircularArray{T,N,A}}) where {T,N,A} = IndexCartesian()
5363
Base.IndexStyle(::Type{<:CircularVector}) = IndexLinear()
5464

65+
function Base.showarg(io::IO, arr::CircularArray, toplevel)
66+
print(io, ndims(arr) == 1 ? "CircularVector(" : "CircularArray(")
67+
Base.showarg(io, parent(arr), false)
68+
print(io, ')')
69+
# toplevel && print(io, " with eltype ", eltype(arr))
70+
end
71+
5572
end

test/runtests.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ end
3939
@test !isa(v1, AbstractVector{String})
4040
@test v1[2] == v1[2 + length(v1)]
4141

42+
@test IndexStyle(v1) == IndexLinear()
4243
@test v1[0] == data[end]
4344
@test v1[-4:10] == [data; data; data]
4445
@test v1[-3:1][-1] == data[end]
@@ -65,11 +66,25 @@ end
6566
a1 = CircularArray(b_arr)
6667
@test size(a1) == (3, 4)
6768
@test a1[2, 3] == 14
69+
@test a1[2, Int32(3)] == 14
6870
a1[2, 3] = 17
6971
@test a1[2, 3] == 17
7072
@test a1[-1, 7] == 17
73+
@test a1[CartesianIndex(-1, 7)] == 17
7174
@test a1[-1:5, 4:10][1, 4] == 17
7275
@test a1[:, -1:-1][2, 1] == 17
76+
a1[CartesianIndex(-2, 7)] = 99
77+
@test a1[1, 3] == 99
78+
79+
@test IndexStyle(a1) == IndexCartesian()
80+
@test a1[3] == a1[3,1]
81+
@test a1[Int32(4)] == a1[1,2]
82+
@test a1[-1] == a1[length(a1)-1]
83+
84+
@test a1[2, 3, 1] == 17 # trailing index
85+
@test a1[2, 3, 99] == 17
86+
@test a1[2, 3, :] == [17]
87+
7388
@test !isa(a1, CircularVector)
7489
@test !isa(a1, AbstractVector)
7590
@test isa(a1, AbstractArray)
@@ -80,6 +95,28 @@ end
8095
@test isa(a2, CircularArray{Int, 2})
8196
end
8297

98+
@testset "3-array" begin
99+
t3 = collect(reshape('a':'x', 2,3,4))
100+
c3 = CircularArray(t3)
101+
102+
@test c3[1,3,3] == c3[3,3,3] == c3[3,3,7] == c3[3,3,7,1]
103+
104+
c3[3,3,7] = 'Z'
105+
@test t3[1,3,3] == 'Z'
106+
107+
@test c3[3, CartesianIndex(3,7)] == 'Z'
108+
c3[Int32(3), CartesianIndex(3,7)] = 'ζ'
109+
@test t3[1,3,3] == 'ζ'
110+
111+
@test vec(c3[:, [CartesianIndex()], 1, 5]) == vec(t3[:, 1, 1])
112+
113+
@test IndexStyle(c3) == IndexCartesian()
114+
@test c3[-1] == t3[length(t3)-1]
115+
116+
@test_throws BoundsError c3[2,3] # too few indices
117+
@test_throws BoundsError c3[CartesianIndex(2,3)]
118+
end
119+
83120
@testset "offset indices" begin
84121
i = OffsetArray(1:5,-3)
85122
a = CircularArray(i)

0 commit comments

Comments
 (0)