Skip to content

Commit 01ea146

Browse files
author
Andy Ferris
committed
Made Size use more consistent.
Removed type unstable behaviour of similar, fixed #22
1 parent 1f035b4 commit 01ea146

File tree

3 files changed

+110
-10
lines changed

3 files changed

+110
-10
lines changed

src/SizedArray.jl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,42 @@ array may be reshaped.
1212
immutable SizedArray{S,T,N,M} <: StaticArray{T,N}
1313
data::Array{T,M}
1414

15-
function SizedArray(a)
15+
function SizedArray(a::Array)
1616
if length(a) != prod(S)
1717
error("Dimensions $(size(a)) don't match static size $S")
1818
end
1919
new(a)
2020
end
21+
22+
function SizedArray()
23+
new(Array{T,M}(S))
24+
end
2125
end
2226

2327
@inline (::Type{SizedArray{S,T,N}}){S,T,N,M}(a::Array{T,M}) = SizedArray{S,T,N,M}(a)
2428
@inline (::Type{SizedArray{S,T}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,_ndims(S),M}(a)
2529
@inline (::Type{SizedArray{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,_ndims(S),M}(a)
2630

31+
@inline (::Type{SizedArray{S,T,N}}){S,T,N}() = SizedArray{S,T,N,N}()
32+
@inline (::Type{SizedArray{S,T}}){S,T}() = SizedArray{S,T,_ndims(S),_ndims(S)}()
33+
34+
@generated function (::Type{SizedArray{S,T,N,M}}){S,T,N,M,L}(x::NTuple{L})
35+
if L != prod(S)
36+
error("Dimension mismatch")
37+
end
38+
exprs = [:(a[$i] = x[$i]) for i = 1:L]
39+
return quote
40+
$(Expr(:meta, :inline))
41+
a = SizedArray{S,T,N,M}()
42+
@inbounds $(Expr(:block, exprs...))
43+
return a
44+
end
45+
end
46+
47+
@inline (::Type{SizedArray{S,T,N}}){S,T,N}(x::Tuple) = SizedArray{S,T,N,N}(x)
48+
@inline (::Type{SizedArray{S,T}}){S,T}(x::Tuple) = SizedArray{S,T,_dims(S),_dims(S)}(x)
49+
@inline (::Type{SizedArray{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,_dims(S),_dims(S)}(x)
50+
2751
# Overide some problematic default behaviour
2852
@inline convert{SA<:SizedArray}(::Type{SA}, sa::SizedArray) = SA(sa.data)
2953

@@ -38,10 +62,14 @@ end
3862
@propagate_inbounds setindex!(a::SizedArray, v, i::Int) = setindex!(a.data, v, i)
3963

4064
typealias SizedVector{S,T,M} SizedArray{S,T,1,M}
65+
@pure size{S}(::Type{SizedVector{S}}) = S
4166
@inline (::Type{SizedVector{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,1,M}(a)
67+
@inline (::Type{SizedVector{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,1,1}(x)
4268

4369
typealias SizedMatrix{S,T,M} SizedArray{S,T,2,M}
70+
@pure size{S}(::Type{SizedMatrix{S}}) = S
4471
@inline (::Type{SizedMatrix{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,2,M}(a)
72+
@inline (::Type{SizedMatrix{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,2,2}(x)
4573

4674

4775
"""

src/abstractarray.jl

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ end
4141
@pure function similar_type{SA<:StaticArray,T}(::Union{SA,Type{SA}}, ::Type{T}, size::Int)
4242
similar_type(similar_type(SA, T), size)
4343
end
44+
@pure function similar_type{SA<:StaticArray,T,S}(::Union{SA,Type{SA}}, ::Type{T}, size::Size{S})
45+
similar_type(similar_type(SA, T), size)
46+
end
4447
@generated function similar_type{SA<:StaticArray,T}(::Union{SA,Type{SA}}, ::Type{T})
4548
# This function has a strange error (on tests) regarding double-inference, if it is marked @pure
4649
if T == eltype(SA)
@@ -115,6 +118,25 @@ end
115118

116119
@pure similar_type{SA<:StaticArray,N}(::Union{SA,Type{SA}}, sizes::Tuple{Vararg{Int,N}}) = SArray{sizes, eltype(SA), N, prod(sizes)}
117120

121+
@generated function similar_type{SA <: StaticArray,S}(::Union{SA,Type{SA}}, ::Size{S})
122+
if length(S) == 1
123+
return quote
124+
$(Expr(:meta, :inline))
125+
SVector{$(S[1]), $(eltype(SA))}
126+
end
127+
elseif length(S) == 2
128+
return quote
129+
$(Expr(:meta, :inline))
130+
SMatrix{$(S[1]), $(S[2]), $(eltype(SA))}
131+
end
132+
else
133+
return quote
134+
$(Expr(:meta, :inline))
135+
SArray{S, $(eltype(SA)), $(length(S)), $(prod(S))}
136+
end
137+
end
138+
end
139+
118140
# Some specializations for the mutable case
119141
@pure similar_type{MA<:Union{MVector,MMatrix,MArray,SizedArray}}(::Union{MA,Type{MA}}, size::Int) = MVector{size, eltype(MA)}
120142
@pure similar_type{MA<:Union{MVector,MMatrix,MArray,SizedArray}}(::Union{MA,Type{MA}}, sizes::Tuple{Int}) = MVector{sizes[1], eltype(MA)}
@@ -123,23 +145,73 @@ end
123145

124146
@pure similar_type{MA<:Union{MVector,MMatrix,MArray,SizedArray},N}(::Union{MA,Type{MA}}, sizes::Tuple{Vararg{Int,N}}) = MArray{sizes, eltype(MA), N, prod(sizes)}
125147

148+
@generated function similar_type{MA<:Union{MVector,MMatrix,MArray,SizedArray},S}(::Union{MA,Type{MA}}, ::Size{S})
149+
if length(S) == 1
150+
return quote
151+
$(Expr(:meta, :inline))
152+
MVector{$(S[1]), $(eltype(MA))}
153+
end
154+
elseif length(S) == 2
155+
return quote
156+
$(Expr(:meta, :inline))
157+
MMatrix{$(S[1]), $(S[2]), $(eltype(MA))}
158+
end
159+
else
160+
return quote
161+
$(Expr(:meta, :inline))
162+
MArray{S, $(eltype(MA)), $(length(S)), $(prod(S))}
163+
end
164+
end
165+
end
166+
126167
# And also similar() returning mutable StaticArrays
127168
@inline similar{SV <: StaticVector}(::SV) = MVector{length(SV),eltype(SV)}()
128169
@inline similar{SV <: StaticVector, T}(::SV, ::Type{T}) = MVector{length(SV),T}()
129-
@inline similar{SA <: StaticArray}(::SA, sizes::Tuple{Int}) = MVector{sizes[1], eltype(SA)}()
130-
@inline similar{SA <: StaticArray}(::SA, size::Int) = MVector{size, eltype(SA)}()
131-
@inline similar{T}(::StaticArray, ::Type{T}, sizes::Tuple{Int}) = MVector{sizes[1],T}()
132-
@inline similar{T}(::StaticArray, ::Type{T}, size::Int) = MVector{size,T}()
133170

134171
@inline similar{SM <: StaticMatrix}(m::SM) = MMatrix{size(SM,1),size(SM,2),eltype(SM),length(SM)}()
135172
@inline similar{SM <: StaticMatrix, T}(::SM, ::Type{T}) = MMatrix{size(SM,1),size(SM,2),T,length(SM)}()
136-
@inline similar{SA <: StaticArray}(::SA, sizes::Tuple{Int,Int}) = MMatrix{sizes[1], sizes[2], eltype(SA), sizes[1]*sizes[2]}()
137-
@inline similar(a::StaticArray, T::Type, sizes::Tuple{Int,Int}) = MMatrix{sizes[1], sizes[2], T, sizes[1]*sizes[2]}()
138173

139174
@inline similar{SA <: StaticArray}(m::SA) = MArray{size(SA),eltype(SA),ndims(SA),length(SA)}()
140175
@inline similar{SA <: StaticArray,T}(m::SA, ::Type{T}) = MArray{size(SA),T,ndims(SA),length(SA)}()
141-
@inline similar{SA <: StaticArray,N}(m::SA, sizes::NTuple{N, Int}) = MArray{sizes,eltype(SA),N,prod(sizes)}()
142-
@inline similar{SA <: StaticArray,N,T}(m::SA, ::Type{T}, sizes::NTuple{N, Int}) = MArray{sizes,T,N,prod(sizes)}()
176+
177+
@generated function similar{SA <: StaticArray,S}(::SA, ::Size{S})
178+
if length(S) == 1
179+
return quote
180+
$(Expr(:meta, :inline))
181+
MVector{$(S[1]), $(eltype(SA))}()
182+
end
183+
elseif length(S) == 2
184+
return quote
185+
$(Expr(:meta, :inline))
186+
MMatrix{$(S[1]), $(S[2]), $(eltype(SA))}()
187+
end
188+
else
189+
return quote
190+
$(Expr(:meta, :inline))
191+
MArray{S, $(eltype(SA))}()
192+
end
193+
end
194+
end
195+
196+
@generated function similar{SA <: StaticArray, T, S}(::SA, ::Type{T}, ::Size{S})
197+
if length(S) == 1
198+
return quote
199+
$(Expr(:meta, :inline))
200+
MVector{$(S[1]), T}()
201+
end
202+
elseif length(S) == 2
203+
return quote
204+
$(Expr(:meta, :inline))
205+
MMatrix{$(S[1]), $(S[2]), T}()
206+
end
207+
else
208+
return quote
209+
$(Expr(:meta, :inline))
210+
MArray{S, T}()
211+
end
212+
end
213+
end
214+
143215

144216
# This is used in Base.LinAlg quite a lot, and it impacts type stability
145217
# since some functions like expm() branch on a check for Hermitian or Symmetric

src/matrix_multiply.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ end
280280
if can_blas && size(A,1)*size(A,2)*size(B,2) >= 14*14*14
281281
return quote
282282
$(Expr(:meta, :inline))
283-
C = similar(A, $T, $s)
283+
C = similar(A, $T, $(Size(s)))
284284
A_mul_B_blas!(C, A, B)
285285
return C
286286
end

0 commit comments

Comments
 (0)