Skip to content

Commit 717b881

Browse files
committed
New implementation based on julia-0.5 infrastructure
1 parent 4d60693 commit 717b881

File tree

3 files changed

+346
-113
lines changed

3 files changed

+346
-113
lines changed

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
julia 0.2-
1+
julia 0.5-

src/OffsetArrays.jl

Lines changed: 81 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,97 @@
11
module OffsetArrays
22

3-
#import Base: Array
4-
importall Base
3+
Base.@deprecate_binding (..) Colon()
54

6-
export OffsetArray, ..
5+
using Base: SimIdx, Indices, LinearSlow, LinearFast
76

8-
type OffsetArray{T<:Number, N, A<:AbstractArray} <: AbstractArray
7+
export OffsetArray
98

9+
immutable OffsetArray{T,N,AA<:AbstractArray} <: AbstractArray{T,N}
10+
parent::AA
1011
offsets::NTuple{N,Int}
11-
array::A
12-
o1::Int
13-
o2::Int
14-
o3::Int
15-
o4::Int
16-
o5::Int
17-
18-
function OffsetArray(r::Range1{Int})
19-
array = Array(T, length(r))
20-
offs = (1 - minimum(r),)
21-
new(offs, array, offs[1])
22-
end
23-
24-
function OffsetArray(r1::Range1{Int}, r2::Range1{Int})
25-
dims = (length(r1), length(r2))
26-
array = Array(T, dims)
27-
offs = (1 - minimum(r1), 1 - minimum(r2))
28-
new(offs, array, offs[1], offs[2])
29-
end
30-
31-
function OffsetArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int})
32-
dims = (length(r1), length(r2), length(r3))
33-
array = Array(T, dims)
34-
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3))
35-
new(offs, array, offs[1], offs[2], offs[3])
36-
end
37-
38-
function OffsetArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int}, r4::Range1{Int})
39-
dims = (length(r1), length(r2), length(r3), length(r4))
40-
array = Array(T, dims)
41-
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3), 1 - minimum(r4))
42-
new(offs, array, offs[1], offs[2], offs[3], offs[4])
43-
end
44-
45-
function OffsetArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int}, r4::Range1{Int}, r5::Range1{Int})
46-
dims = (length(r1), length(r2), length(r3), length(r4), length(r5))
47-
array = Array(T, dims)
48-
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3), 1 - minimum(r4), 1 - minimum(r5))
49-
new(offs, array, offs[1], offs[2], offs[3], offs[4], offs[5])
50-
end
51-
52-
function OffsetArray(r::Range1{Int}...)
53-
dims = map((x) -> length(x), r)
54-
array = Array(T, dims)
55-
offs = map((x) -> 1 - minimum(x), r)
56-
new(offs, array)
57-
end
58-
12+
end
13+
typealias OffsetVector{T,AA<:AbstractArray} OffsetArray{T,1,AA}
14+
15+
OffsetArray{T,N}(A::AbstractArray{T,N}, offsets::NTuple{N,Int}) = OffsetArray{T,N,typeof(A)}(A, offsets)
16+
OffsetArray{T,N}(A::AbstractArray{T,N}, offsets::Vararg{Int,N}) = OffsetArray(A, offsets)
17+
18+
(::Type{OffsetArray{T,N}}){T,N}(inds::Indices{N}) = OffsetArray{T,N,Array{T,N}}(Array{T,N}(map(Base.dimlength, inds)), map(indsoffset, inds))
19+
(::Type{OffsetArray{T}}){T,N}(inds::Indices{N}) = OffsetArray{T,N}(inds)
20+
OffsetArray{T,N}(::Type{T}, inds::Vararg{UnitRange{Int},N}) = OffsetArray{T,N}(inds)
21+
22+
Base.linearindexing{T<:OffsetArray}(::Type{T}) = Base.linearindexing(parenttype(T))
23+
Base.indicesbehavior{T<:OffsetArray}(::Type{T}) = Base.IndicesUnitRange()
24+
parenttype{T,N,AA}(::Type{OffsetArray{T,N,AA}}) = AA
25+
parenttype(A::OffsetArray) = parenttype(typeof(A))
26+
27+
Base.parent(A::OffsetArray) = A.parent
28+
Base.size(A::OffsetArray) = size(parent(A))
29+
Base.eachindex(::LinearSlow, A::OffsetArray) = CartesianRange(indices(A))
30+
Base.eachindex(::LinearFast, A::OffsetVector) = indices(A, 1)
31+
Base.summary(A::OffsetArray) = string(typeof(A))*" with indices "*string(indices(A))
32+
33+
# Implementations of indices and indices1. Since bounds-checking is
34+
# performance-critical and relies on indices, these are usually worth
35+
# optimizing thoroughly.
36+
@inline Base.indices(A::OffsetArray, d) = 1 <= d <= length(A.offsets) ? (o = A.offsets[d]; (1+o:size(parent(A),d)+o)) : (1:1)
37+
@inline Base.indices(A::OffsetArray) = _indices((), A) # would rather use ntuple, but see #15276
38+
@inline _indices{T,N}(out::NTuple{N}, A::OffsetArray{T,N}) = out
39+
@inline _indices(out, A::OffsetArray) = (d = length(out)+1; o = A.offsets[d]; _indices((out..., (1+o:size(parent(A),d)+o)), A))
40+
# By optimizing indices1 we can avoid a branch on the dim-check
41+
Base.indices1{T}(A::OffsetArray{T,0}) = 1:1
42+
@inline Base.indices1(A::OffsetArray) = (o = A.offsets[1]; 1+o:size(parent(A),1)+o)
43+
44+
function Base.similar(A::OffsetArray, T::Type, dims::Dims)
45+
B = similar(parent(A), T, dims)
46+
end
47+
function Base.similar(A::AbstractArray, T::Type, inds::Tuple{Vararg{SimIdx}})
48+
B = similar(A, T, map(Base.dimlength, inds))
49+
OffsetArray(B, map(indsoffset, inds))
5950
end
6051

61-
OffsetArray(T, r::Range1{Int}...) = OffsetArray{T, length(r,), Array{T, length(r,)}}(r...)
62-
63-
getindex{T<:Number}(FA::OffsetArray{T,1}, i1::Int) = FA.array[i1+FA.o1]
64-
getindex{T<:Number}(FA::OffsetArray{T,2}, i1::Int, i2::Int) = FA.array[i1+FA.o1, i2+FA.o2]
65-
getindex{T<:Number}(FA::OffsetArray{T,3}, i1::Int, i2::Int, i3::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3]
66-
getindex{T<:Number}(FA::OffsetArray{T,4}, i1::Int, i2::Int, i3::Int, i4::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4]
67-
getindex{T<:Number}(FA::OffsetArray{T,5}, i1::Int, i2::Int, i3::Int, i4::Int, i5::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4, i5+FA.o5]
68-
69-
# a generic but not very efficient case
70-
getindex{T<:Number,N}(FA::OffsetArray{T,N}, I::Int...) = let ind = [I[i] + FA.offsets[i] for i = 1:length(I)]; return FA.array[ind...] end
71-
72-
setindex!{T<:Number}(FA::OffsetArray{T,1}, x, i1::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1)
73-
setindex!{T<:Number}(FA::OffsetArray{T,2}, x, i1::Int, i2::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2)
74-
setindex!{T<:Number}(FA::OffsetArray{T,3}, x, i1::Int, i2::Int, i3::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3)
75-
setindex!{T<:Number}(FA::OffsetArray{T,4}, x, i1::Int, i2::Int, i3::Int, i4::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4)
76-
setindex!{T<:Number}(FA::OffsetArray{T,5}, x, i1::Int, i2::Int, i3::Int, i4::Int, i5::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4, i5+FA.o5)
77-
78-
# a generic not very efficient case
79-
setindex!{T<:Number,N}(FA::OffsetArray{T,N}, x, I::Int...) = let ind = [I[i] + FA.offsets[i] for i = 1:length(I)]; arrayset(FA.array, convert(T,x), ind...) end
80-
81-
Base.print(a::OffsetArray) = Base.print(a.array)
82-
Base.display(a::OffsetArray) = Base.display(a.array)
83-
84-
Base.size(a::OffsetArray) = arraysize(a.array)
85-
Base.size(a::OffsetArray, d) = arraysize(a.array, d)
86-
87-
88-
# as the parser changes colons into ranges.
89-
# for avoiding to write a[Colon()] a whole range .. is introduced
90-
# it is possible to write say a[..] = b[..]
91-
92-
const (..) = Colon()
93-
94-
getindex{T<:Number}(FA::OffsetArray{T,1}, r1::Union(Range1{Int},Colon)) =
95-
isa(r1, Colon) ? FA.array[:] : FA.array[r1+FA.o1]
96-
97-
getindex{T<:Number}(FA::OffsetArray{T,2}, r1::Union(Range1{Int},Colon), i2::Int) =
98-
isa(r1, Colon) ? FA.array[:, i2+FA.o2] : FA.array[r1+FA.o1, i2+FA.o2]
52+
Base.allocate_for(f, A::OffsetArray, shape::SimIdx) = OffsetArray(f(Base.dimlength(shape)), (indsoffset(shape),))
53+
Base.allocate_for(f, A::OffsetArray, shape::Tuple{Vararg{SimIdx}}) = OffsetArray(f(map(Base.dimlength, shape)), map(indsoffset, shape))
54+
Base.promote_indices(a::OffsetArray, b::OffsetArray) = a
9955

100-
getindex{T<:Number}(FA::OffsetArray{T,3}, r1::Union(Range1{Int},Colon), i2::Int, i3::Int) =
101-
isa(r1, Colon) ? FA.array[:, i2+FA.o2, i3+FA.o3] : FA.array[r1+FA.o1, i2+FA.o2, i3+FA.o3]
56+
Base.reshape(A::AbstractArray, inds::Indices) = OffsetArray(reshape(A, map(Base.dimlength, inds)), map(indsoffset, inds))
10257

103-
setindex!{T<:Number}(FA::OffsetArray{T,1}, x, r1::Union(Range1{Int},Colon)) = let
104-
if isa(r1, Colon)
105-
FA.array[:] = x[:]
106-
else
107-
FA.array[r1+FA.o1] = x[r1+FA.o1]
108-
end
58+
@inline function Base.getindex{T,N}(A::OffsetArray{T,N}, I::Vararg{Int,N})
59+
@boundscheck checkbounds(A, I...)
60+
@inbounds ret = parent(A)[offset(A.offsets, I)...]
61+
ret
10962
end
110-
111-
setindex!{T<:Number}(FA::OffsetArray{T,2}, x, r1::Union(Range1{Int},Colon), i2::Int) = let
112-
if isa(r1, Colon)
113-
FA.array[:, i2+FA.o2] = x[:, i2+FA.o2]
114-
else
115-
FA.array[r1+FA.o1, i2+FA.o2] = x[r1+FA.o1, i2+FA.o2]
116-
end
63+
@inline function Base._getindex(::LinearFast, A::OffsetVector, i::Int)
64+
@boundscheck checkbounds(A, i)
65+
@inbounds ret = parent(A)[offset(A.offsets, (i,))[1]]
66+
ret
11767
end
118-
119-
setindex!{T<:Number}(FA::OffsetArray{T,3}, x, r1::Union(Range1{Int},Colon), i2::Int, i3::Int) = let
120-
if isa(r1, Colon)
121-
FA.array[:, i2+FA.o2, i3+FA.o3] = x[:, i2+FA.o2, i3+FA.o3]
122-
else
123-
FA.array[r1+FA.o1, i2+FA.o2, i3+FA.o3] = x[r1+FA.o1, i2+FA.o2, i3+FA.o3]
124-
end
68+
@inline function Base._getindex(::LinearFast, A::OffsetArray, i::Int)
69+
@boundscheck checkbounds(A, i)
70+
@inbounds ret = parent(A)[i]
71+
ret
72+
end
73+
@inline function Base.setindex!{T,N}(A::OffsetArray{T,N}, val, I::Vararg{Int,N})
74+
@boundscheck checkbounds(A, I...)
75+
@inbounds parent(A)[offset(A.offsets, I)...] = val
76+
val
77+
end
78+
@inline function Base._setindex!(::LinearFast, A::OffsetVector, val, i::Int)
79+
@boundscheck checkbounds(A, i)
80+
@inbounds parent(A)[offset(A.offsets, (i,))[1]] = val
81+
val
12582
end
83+
@inline function Base._setindex!(::LinearFast, A::OffsetArray, val, i::Int)
84+
@boundscheck checkbounds(A, i)
85+
@inbounds parent(A)[i] = val
86+
val
87+
end
88+
89+
# Computing a shifted index (subtracting the offset)
90+
offset{N}(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) = _offset((), offsets, inds)
91+
_offset(out, ::Tuple{}, ::Tuple{}) = out
92+
@inline _offset(out, offsets, inds) = _offset((out..., inds[1]-offsets[1]), Base.tail(offsets), Base.tail(inds))
12693

94+
indsoffset(r::Range) = first(r) - 1
95+
indsoffset(i::Integer) = 0
12796

12897
end # module

0 commit comments

Comments
 (0)