Skip to content

Commit 1f035b4

Browse files
author
Andy Ferris
committed
Implement reshape() using Size{}
* Use the `Size` trait for performing statically sized reshapes. * Deprecate old methods * Improve SizedArray to allow a cost-free reshaped view.
1 parent 88cadf0 commit 1f035b4

File tree

3 files changed

+53
-143
lines changed

3 files changed

+53
-143
lines changed

src/SizedArray.jl

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,44 @@
44
55
Wraps an `Array` with a static size, so to take advantage of the (faster)
66
methods defined by the static array package. The size is checked once upon
7-
construction.
7+
construction to determine if the number of elements (`length`) match, but the
8+
array may be reshaped.
89
910
(Also, `Size(dims...)(array)` acheives the same thing)
1011
"""
11-
immutable SizedArray{S,T,N} <: StaticArray{T,N}
12-
data::Array{T,N}
12+
immutable SizedArray{S,T,N,M} <: StaticArray{T,N}
13+
data::Array{T,M}
1314

1415
function SizedArray(a)
15-
if size(a) != S
16+
if length(a) != prod(S)
1617
error("Dimensions $(size(a)) don't match static size $S")
1718
end
1819
new(a)
1920
end
2021
end
2122

22-
@inline (::Type{SizedArray{S,T}}){S,T,N}(a::Array{T,N}) = SizedArray{S,T,N}(a)
23-
@inline (::Type{SizedArray{S}}){S,T,N}(a::Array{T,N}) = SizedArray{S,T,N}(a)
23+
@inline (::Type{SizedArray{S,T,N}}){S,T,N,M}(a::Array{T,M}) = SizedArray{S,T,N,M}(a)
24+
@inline (::Type{SizedArray{S,T}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,_ndims(S),M}(a)
25+
@inline (::Type{SizedArray{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,_ndims(S),M}(a)
26+
27+
# Overide some problematic default behaviour
28+
@inline convert{SA<:SizedArray}(::Type{SA}, sa::SizedArray) = SA(sa.data)
29+
30+
@pure _ndims{N}(::NTuple{N,Int}) = N
2431

2532
@pure size{S}(::Type{SizedArray{S}}) = S
2633
@pure size{S,T}(::Type{SizedArray{S,T}}) = S
2734
@pure size{S,T,N}(::Type{SizedArray{S,T,N}}) = S
35+
@pure size{S,T,N,M}(::Type{SizedArray{S,T,N,M}}) = S
2836

29-
@propagate_inbounds getindex(a::SizedArray, i::Int) = getindex(a.data, i...)
30-
@propagate_inbounds setindex!(a::SizedArray, v, i::Int) = setindex!(a.data, v, i...)
37+
@propagate_inbounds getindex(a::SizedArray, i::Int) = getindex(a.data, i)
38+
@propagate_inbounds setindex!(a::SizedArray, v, i::Int) = setindex!(a.data, v, i)
3139

32-
typealias SizedVector{S,T} SizedArray{S,T,1}
33-
@inline (::Type{SizedVector{S}}){S,T}(a::Vector{T}) = SizedArray{S,T,1}(a)
40+
typealias SizedVector{S,T,M} SizedArray{S,T,1,M}
41+
@inline (::Type{SizedVector{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,1,M}(a)
3442

35-
typealias SizedMatrix{S,T} SizedArray{S,T,2}
36-
@inline (::Type{SizedMatrix{S}}){S,T}(a::Matrix{T}) = SizedArray{S,T,2}(a)
43+
typealias SizedMatrix{S,T,M} SizedArray{S,T,2,M}
44+
@inline (::Type{SizedMatrix{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,2,M}(a)
3745

3846

3947
"""

src/abstractarray.jl

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,17 @@ end
175175
end
176176
end
177177

178-
# Reshape uses types to specify size (and also conveniently, the output type)
178+
# Reshape used types to specify size (and also conveniently, the output type)
179179
@generated function reshape{SA<:StaticArray}(a::StaticArray, ::Type{SA})
180180
if !(SA <: StaticVector) && length(a) != length(SA)
181181
error("Static array of size $(size(a)) cannot be reshaped to size $(size(SA))")
182182
end
183183

184+
Base.depwarn("Use reshape(array, Size(dims...)) rather than reshape(array, StaticArrayType)", :reshape)
185+
184186
return quote
185187
$(Expr(:meta, :inline))
186-
return SA(tuple(a))
188+
return SA(Tuple(a))
187189
end
188190
end
189191

@@ -192,5 +194,31 @@ function reshape{SA<:StaticArray}(a::AbstractArray, ::Type{SA})
192194
error("Static array of size $(size(a)) cannot be reshaped to size $(size(SA))")
193195
end
194196

197+
Base.depwarn("Use reshape(array, Size(dims...)) rather than reshape(array, StaticArrayType)", :reshape)
198+
195199
return SA((a...))
196200
end
201+
202+
203+
# Versions using Size{}
204+
@generated function reshape{S}(a::StaticArray, ::Size{S})
205+
if length(a) != prod(S)
206+
error("Static array of size $(size(a)) cannot be reshaped to size $S")
207+
end
208+
209+
newtype = similar_type(a, S)
210+
211+
return quote
212+
$(Expr(:meta, :inline))
213+
return $newtype(a)
214+
end
215+
end
216+
217+
@generated function reshape{S}(a::Array, ::Size{S})
218+
newtype = SizedArray{S, eltype(a), length(S)}
219+
220+
return quote
221+
$(Expr(:meta, :inline))
222+
return $newtype(a)
223+
end
224+
end

test/abstractarray.jl

Lines changed: 3 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -63,135 +63,9 @@
6363
@test isa(similar(sv, (3,3,3)), MArray{(3,3,3),Int,3,27})
6464
@test isa(similar(sv, Float64, (3,3,3)), MArray{(3,3,3),Float64,3,27})
6565
end
66-
#=
67-
@testset "size and length" begin
68-
vec = [1,2,3,4]
69-
sv = SVector{(4,)}(vec)
70-
mv = MVector{(4,)}(vec)
71-
72-
mat = eye(3)
73-
sm = MMatrix{(3,3)}(mat)
74-
mm = MMatrix{(3,3)}(mat)
75-
76-
@test size(sv) == size(vec)
77-
@test size(mv) == size(vec)
78-
@test size(sm) == size(mat)
79-
@test size(mm) == size(mat)
80-
81-
@test size(sv,1) == size(vec,1)
82-
@test size(mv,1) == size(vec,1)
83-
@test size(sm,1) == size(mat,1)
84-
@test size(mm,1) == size(mat,1)
85-
@test size(sv,2) == size(vec,2) # Test for
86-
@test size(mv,2) == size(vec,2) # trailing 1's
87-
@test size(sm,2) == size(mat,2)
88-
@test size(mm,2) == size(mat,2)
89-
90-
@test length(sv) == length(vec)
91-
@test length(mv) == length(vec)
92-
@test length(sm) == length(mat)
93-
@test length(mm) == length(mat)
94-
95-
@test size(typeof(sv)) == size(vec)
96-
@test size(typeof(mv)) == size(vec)
97-
@test size(typeof(sm)) == size(mat)
98-
@test size(typeof(mm)) == size(mat)
99-
100-
@test size(typeof(sv),1) == size(vec,1)
101-
@test size(typeof(mv),1) == size(vec,1)
102-
@test size(typeof(sm),1) == size(mat,1)
103-
@test size(typeof(mm),1) == size(mat,1)
104-
@test size(typeof(sv),2) == size(vec,2) # Test for
105-
@test size(typeof(mv),2) == size(vec,2) # trailing 1's
106-
@test size(typeof(sm),2) == size(mat,2)
107-
@test size(typeof(mm),2) == size(mat,2)
108-
109-
@test length(typeof(sv)) == length(vec)
110-
@test length(typeof(mv)) == length(vec)
111-
@test length(typeof(sm)) == length(mat)
112-
@test length(typeof(mm)) == length(mat)
113-
end
114-
115-
@testset "Miscellanious introspection" begin
116-
vec = [1,2,3,4]
117-
sv = SVector{(4,)}(vec)
118-
mv = MVector{(4,)}(vec)
119-
120-
@test Base.isassigned(sv, 4) == Base.isassigned(vec, 4)
121-
@test Base.isassigned(sv, 5) == Base.isassigned(vec, 5)
122-
@test Base.isassigned(sv, 2, 1) == Base.isassigned(vec, 2, 1) # test for trailing ones
123-
@test Base.isassigned(mv, 4) == Base.isassigned(vec, 4)
124-
@test Base.isassigned(mv, 5) == Base.isassigned(vec, 5)
125-
@test Base.isassigned(mv, 2, 1) == Base.isassigned(vec, 2, 1)
12666

127-
@test Base.linearindexing(sv) == Base.LinearFast()
128-
@test Base.linearindexing(mv) == Base.LinearFast()
129-
@test Base.linearindexing(typeof(sv)) == Base.LinearFast()
130-
@test Base.linearindexing(typeof(mv)) == Base.LinearFast()
67+
@testset "reshape" begin
68+
@test reshape(SVector(1,2,3,4), Size(2,2)) === SMatrix{2,2}(1,2,3,4)
69+
@test reshape([1,2,3,4], Size(2,2))::SizedArray{(2,2),Int,2,1} == [1 3; 2 4]
13170
end
132-
133-
@testset "similar and similar_type" begin
134-
vec = [1,2,3,4]
135-
sv = SVector{(4,)}(vec)
136-
mv = MVector{(4,)}(vec)
137-
138-
@test_throws Exception similar(sv)
139-
@test typeof(similar(mv)) == typeof(mv)
140-
@test_inferred similar(mv)
141-
@test_throws Exception similar(sv, Float64)
142-
@test typeof(similar(mv, Float64)) <: MVector{(4,),Float64}
143-
@test_inferred similar(mv, Float64)
144-
@test_throws Exception similar(sv, (2,2))
145-
@test_throws Exception similar(mv, (2,2))
146-
@test_throws Exception similar(sv, Float64, (2,2))
147-
@test_throws Exception similar(mv, Float64, (2,2))
148-
@test_throws Exception similar(sv, Val{(2,2)})
149-
@test typeof(similar(mv, Val{(2,2)})) <: MArray{(2,2),Int}
150-
@test_inferred similar(mv, Val{(2,2)})
151-
@test_throws Exception similar(sv, Float64, Val{(2,2)})
152-
@test typeof(similar(mv, Float64, Val{(2,2)})) <: MArray{(2,2),Float64}
153-
@test_inferred similar(mv, Float64, Val{(2,2)})
154-
155-
@test similar_type(sv) == typeof(sv)
156-
@test_inferred similar_type(sv)
157-
@test similar_type(mv) == typeof(mv)
158-
@test_inferred similar_type(mv)
159-
@test similar_type(sv, Float64) == SArray{(4,),Float64,1,NTuple{4,Float64}}
160-
@test_inferred similar_type(sv, Float64)
161-
@test similar_type(mv, Float64) == MArray{(4,),Float64,1,NTuple{4,Float64}}
162-
@test_inferred similar_type(mv, Float64)
163-
@test_throws Exception similar_type(sv, (2,2))
164-
@test_throws Exception similar_type(mv, (2,2))
165-
@test_throws Exception similar_type(sv, Float64, (2,2))
166-
@test_throws Exception similar_type(mv, Float64, (2,2))
167-
@test similar_type(sv, Val{(2,2)}) == SArray{(2,2),Int,2,NTuple{4,Int}}
168-
@test_inferred similar_type(sv, Val{(2,2)})
169-
@test similar_type(mv, Val{(2,2)}) == MArray{(2,2),Int,2,NTuple{4,Int}}
170-
@test_inferred similar_type(mv, Val{(2,2)})
171-
@test similar_type(sv, Float64, Val{(2,2)}) == SArray{(2,2),Float64,2,NTuple{4,Float64}}
172-
@test_inferred similar_type(sv, Float64, Val{(2,2)})
173-
@test similar_type(mv, Float64, Val{(2,2)}) == MArray{(2,2),Float64,2,NTuple{4,Float64}}
174-
@test_inferred similar_type(mv, Float64, Val{(2,2)})
175-
end
176-
177-
@testset "reshape and permutedims" begin
178-
vec = [4,5,6,7]
179-
sv = SVector{(4,)}(vec)
180-
mv = MVector{(4,)}(vec)
181-
182-
mat = reshape(vec,(2,2))
183-
sm = SMatrix{(2,2)}(mat)
184-
mm = MMatrix{(2,2)}(mat)
185-
186-
@test reshape(sv, Val{(2,2)}) === sm
187-
@test_inferred reshape(sv, Val{(2,2)})
188-
@test reshape(mv, Val{(2,2)}) == mm
189-
@test_inferred reshape(mv, Val{(2,2)})
190-
@test isa(reshape(mv, Val{(2,2)}), MMatrix)
191-
@test_throws Exception reshape(sv, (2,2)) == sm
192-
@test_throws Exception reshape(sv, (2,2)) == sm
193-
194-
end
195-
196-
=#
19771
end

0 commit comments

Comments
 (0)