Skip to content

Commit 0cbb281

Browse files
c42fandyferris
authored andcommitted
Implement promote_rule for StaticArray to mirror Base.Array (#215)
* Implement promote_rule for StaticArray to mirror Base.Array * Many bug fixes and several tests for SizedArray This appears to have been badly broken during the Tuple type parameter consolidation: Some of the constructors didn't work, and the type parameters for SizedVector and SizedMatrix were completely broken. * Restrict promote_rule to SArray, MArray, SizedArray Add this restriction in analogy with the quite restricted version for Base.Array, to avoid unwanted consequences for other static array types.
1 parent ce69d4d commit 0cbb281

File tree

8 files changed

+80
-16
lines changed

8 files changed

+80
-16
lines changed

src/MArray.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,7 @@ macro MArray(ex)
290290
end
291291

292292
end
293+
294+
function promote_rule(::Type{<:MArray{S,T,N,L}}, ::Type{<:MArray{S,U,N,L}}) where {S,T,U,N,L}
295+
MArray{S,promote_type(T,U),N,L}
296+
end

src/SArray.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,7 @@ macro SArray(ex)
252252
error("Bad input for @SArray")
253253
end
254254
end
255+
256+
function promote_rule(::Type{<:SArray{S,T,N,L}}, ::Type{<:SArray{S,U,N,L}}) where {S,T,U,N,L}
257+
SArray{S,promote_type(T,U),N,L}
258+
end

src/SizedArray.jl

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ end
4545
end
4646

4747
@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)
48+
@inline (::Type{SizedArray{S,T}}){S,T}(x::Tuple) = SizedArray{S,T,tuple_length(S),tuple_length(S)}(x)
49+
@inline (::Type{SizedArray{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,tuple_length(S),tuple_length(S)}(x)
5050

5151
# Overide some problematic default behaviour
5252
@inline convert{SA<:SizedArray}(::Type{SA}, sa::SizedArray) = SA(sa.data)
@@ -64,17 +64,13 @@ end
6464
@propagate_inbounds getindex(a::SizedArray, i::Int) = getindex(a.data, i)
6565
@propagate_inbounds setindex!(a::SizedArray, v, i::Int) = setindex!(a.data, v, i)
6666

67-
SizedVector{S,T,M} = SizedArray{S,T,1,M}
68-
@inline (::Type{SizedVector{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,1,M}(a)
69-
@inline (::Type{SizedVector{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,1,1}(x)
70-
@inline (::Type{Vector})(sa::SizedVector) = sa.data
71-
@inline convert(::Type{Vector}, sa::SizedVector) = sa.data
67+
SizedVector{S,T,M} = SizedArray{Tuple{S},T,1,M}
68+
@inline (::Type{SizedVector{S}}){S,T,M}(a::Array{T,M}) = SizedArray{Tuple{S},T,1,M}(a)
69+
@inline (::Type{SizedVector{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{Tuple{S},T,1,1}(x)
7270

73-
SizedMatrix{S,T,M} = SizedArray{S,T,2,M}
74-
@inline (::Type{SizedMatrix{S}}){S,T,M}(a::Array{T,M}) = SizedArray{S,T,2,M}(a)
75-
@inline (::Type{SizedMatrix{S}}){S,T,L}(x::NTuple{L,T}) = SizedArray{S,T,2,2}(x)
76-
@inline (::Type{Matrix})(sa::SizedMatrix) = sa.data
77-
@inline convert(::Type{Matrix}, sa::SizedMatrix) = sa.data
71+
SizedMatrix{S1,S2,T,M} = SizedArray{Tuple{S1,S2},T,2,M}
72+
@inline (::Type{SizedMatrix{S1,S2}}){S1,S2,T,M}(a::Array{T,M}) = SizedArray{Tuple{S1,S2},T,2,M}(a)
73+
@inline (::Type{SizedMatrix{S1,S2}}){S1,S2,T,L}(x::NTuple{L,T}) = SizedArray{Tuple{S1,S2},T,2,2}(x)
7874

7975

8076
"""
@@ -85,3 +81,8 @@ Creates a `SizedArray` wrapping `array` with the specified statically-known
8581
package.
8682
"""
8783
(::Size{S}){S}(a::Array) = SizedArray{Tuple{S...}}(a)
84+
85+
86+
function promote_rule(::Type{<:SizedArray{S,T,N,M}}, ::Type{<:SizedArray{S,U,N,M}}) where {S,T,U,N,M}
87+
SizedArray{S,promote_type(T,U),N,M}
88+
end

src/StaticArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module StaticArrays
55
import Base: @_inline_meta, @_propagate_inbounds_meta, @_pure_meta, @propagate_inbounds, @pure
66

77
import Base: getindex, setindex!, size, similar, vec, show,
8-
length, convert, promote_op, map, map!, reduce, reducedim, mapreducedim,
8+
length, convert, promote_op, promote_rule, map, map!, reduce, reducedim, mapreducedim,
99
mapreduce, broadcast, broadcast!, conj, transpose, ctranspose,
1010
hcat, vcat, ones, zeros, eye, one, cross, vecdot, reshape, fill,
1111
fill!, det, inv, eig, eigvals, expm, sqrtm, trace, vecnorm, norm, dot, diagm,

test/MArray.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,10 @@
132132

133133
@test_throws BoundsError setindex!(v, 4, -1)
134134
end
135+
136+
@testset "promotion" begin
137+
@test @inferred(promote_type(MVector{1,Float64}, MVector{1,BigFloat})) == MVector{1,BigFloat}
138+
@test @inferred(promote_type(MVector{2,Int}, MVector{2,Float64})) === MVector{2,Float64}
139+
@test @inferred(promote_type(MMatrix{2,3,Float32,6}, MMatrix{2,3,Complex{Float64},6})) === MMatrix{2,3,Complex{Float64},6}
140+
end
135141
end

test/SArray.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,10 @@
115115

116116
@test_throws Exception m[1] = 1
117117
end
118+
119+
@testset "promotion" begin
120+
@test @inferred(promote_type(SVector{1,Float64}, SVector{1,BigFloat})) == SVector{1,BigFloat}
121+
@test @inferred(promote_type(SVector{2,Int}, SVector{2,Float64})) === SVector{2,Float64}
122+
@test @inferred(promote_type(SMatrix{2,3,Float32,6}, SMatrix{2,3,Complex{Float64},6})) === SMatrix{2,3,Complex{Float64},6}
123+
end
118124
end

test/SizedArray.jl

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,49 @@
1212
# Bad parameters
1313
@test_throws Exception SizedArray{Tuple{1},Int,2}()
1414
@test_throws Exception SArray{Tuple{3, 4},Int,1}()
15-
15+
1616
# Parameter/input size mismatch
1717
@test_throws Exception SizedArray{Tuple{1},Int,2}([2; 3])
1818
@test_throws Exception SizedArray{Tuple{1},Int,2}((2, 3))
1919
end
2020

21+
@testset "Outer Constructors" begin
22+
# From Array
23+
@test @inferred(SizedArray{Tuple{2},Float64,1}([1,2]))::SizedArray{Tuple{2},Float64,1,1} == [1.0, 2.0]
24+
@test @inferred(SizedArray{Tuple{2},Float64}([1,2]))::SizedArray{Tuple{2},Float64,1,1} == [1.0, 2.0]
25+
@test @inferred(SizedArray{Tuple{2}}([1,2]))::SizedArray{Tuple{2},Int,1,1} == [1,2]
26+
@test @inferred(SizedArray{Tuple{2,2}}([1 2;3 4]))::SizedArray{Tuple{2,2},Int,2,2} == [1 2; 3 4]
27+
# From Array, reshaped
28+
@test @inferred(SizedArray{Tuple{2,2}}([1,2,3,4]))::SizedArray{Tuple{2,2},Int,2,1} == [1 3; 2 4]
29+
# Uninitialized
30+
@test @inferred(SizedArray{Tuple{2,2},Int,2}()) isa SizedArray{Tuple{2,2},Int,2,2}
31+
@test @inferred(SizedArray{Tuple{2,2},Int}()) isa SizedArray{Tuple{2,2},Int,2,2}
32+
33+
# From Tuple
34+
@test @inferred(SizedArray{Tuple{2},Float64,1}((1,2)))::SizedArray{Tuple{2},Float64,1,1} == [1.0, 2.0]
35+
@test @inferred(SizedArray{Tuple{2},Float64}((1,2)))::SizedArray{Tuple{2},Float64,1,1} == [1.0, 2.0]
36+
@test @inferred(SizedArray{Tuple{2}}((1,2)))::SizedArray{Tuple{2},Int,1,1} == [1,2]
37+
@test @inferred(SizedArray{Tuple{2,2}}((1,2,3,4)))::SizedArray{Tuple{2,2},Int,2,2} == [1 3; 2 4]
38+
end
39+
40+
@testset "SizedVector and SizedMatrix" begin
41+
@test @inferred(SizedVector{2}([1,2]))::SizedArray{Tuple{2},Int,1,1} == [1,2]
42+
@test @inferred(SizedVector{2}((1,2)))::SizedArray{Tuple{2},Int,1,1} == [1,2]
43+
# Reshaping
44+
@test @inferred(SizedVector{2}([1 2]))::SizedArray{Tuple{2},Int,1,2} == [1,2]
45+
# Back to Vector
46+
@test Vector(SizedVector{2}((1,2))) == [1,2]
47+
@test convert(Vector, SizedVector{2}((1,2))) == [1,2]
48+
49+
@test @inferred(SizedMatrix{2,2}([1 2; 3 4]))::SizedArray{Tuple{2,2},Int,2,2} == [1 2; 3 4]
50+
# Reshaping
51+
@test @inferred(SizedMatrix{2,2}([1,2,3,4]))::SizedArray{Tuple{2,2},Int,2,1} == [1 3; 2 4]
52+
@test @inferred(SizedMatrix{2,2}((1,2,3,4)))::SizedArray{Tuple{2,2},Int,2,2} == [1 3; 2 4]
53+
# Back to Matrix
54+
@test Matrix(SizedMatrix{2,2}([1 2;3 4])) == [1 2; 3 4]
55+
@test convert(Matrix, SizedMatrix{2,2}([1 2;3 4])) == [1 2; 3 4]
56+
end
57+
2158
# setindex
2259
sa = SizedArray{Tuple{2}, Int, 1}([3, 4])
2360
sa[1] = 2
@@ -32,4 +69,10 @@
3269
@test Matrix(SMatrix{2,2}((1,2,3,4))) == [1 3; 2 4]
3370
@test convert(Matrix, SMatrix{2,2}((1,2,3,4))) == [1 3; 2 4]
3471
end
72+
73+
@testset "promotion" begin
74+
@test @inferred(promote_type(SizedVector{1,Float64,1}, SizedVector{1,BigFloat,1})) == SizedVector{1,BigFloat,1}
75+
@test @inferred(promote_type(SizedVector{2,Int,1}, SizedVector{2,Float64,1})) === SizedVector{2,Float64,1}
76+
@test @inferred(promote_type(SizedMatrix{2,3,Float32,2}, SizedMatrix{2,3,Complex{Float64},2})) === SizedMatrix{2,3,Complex{Float64},2}
77+
end
3578
end

test/abstractarray.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@
6969
@test @inferred(vec(SMatrix{2, 2}([1 2; 3 4])))::SVector{4,Int} == [1, 3, 2, 4]
7070
@test @inferred(copy(SMatrix{2, 2}([1 2; 3 4]))) == [1 2; 3 4]
7171
end
72-
72+
7373
@testset "full" begin
7474
m_a = randn(2,2)
7575
m_a = m_a*m_a.'
7676
m = SMatrix{2,2}(m_a)
7777
@test @inferred(full(Symmetric(m))) == m_a
7878
@test @inferred(full(Symmetric(m, :L))) == m_a
79-
79+
8080
m_a = randn(2,2) + im*randn(2,2)
8181
m_a = m_a*m_a'
8282
m = SMatrix{2,2}(m_a)

0 commit comments

Comments
 (0)