diff --git a/src/convert.jl b/src/convert.jl index 07f2d109..f653d3df 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -11,6 +11,12 @@ @inline convert(::Type{SA}, sa::SA) where {SA<:StaticArray} = sa @inline convert(::Type{SA}, x::Tuple) where {SA<:StaticArray} = SA(x) # convert -> constructor. Hopefully no loops... +# support conversion to AbstractArray +AbstractArray{T}(sa::StaticArray{S,T}) where {S,T} = sa +AbstractArray{T,N}(sa::StaticArray{S,T,N}) where {S,T,N} = sa +AbstractArray{T}(sa::StaticArray{S,U}) where {S,T,U} = similar_type(typeof(sa),T,Size(sa))(sa) +AbstractArray{T,N}(sa::StaticArray{S,U,N}) where {S,T,U,N} = similar_type(typeof(sa),T,Size(sa))(sa) + # Constructing a Tuple from a StaticArray @inline Tuple(a::StaticArray) = unroll_tuple(a, Length(a)) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 41bd3478..000b5189 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -129,6 +129,55 @@ using StaticArrays, Test, LinearAlgebra m = MVector(1, 2, 3) @test @inferred(reverse(m))::typeof(m) == MVector(3, 2, 1) end + + @testset "Conversion to AbstractArray" begin + # Issue #746 + # conversion to AbstractArray changes the eltype from Int to Float64 + sv = SVector(1,2) + @test @inferred(convert(AbstractArray{Float64}, sv)) isa SVector{2,Float64} + @test @inferred(convert(AbstractVector{Float64}, sv)) isa SVector{2,Float64} + @test convert(AbstractArray{Float64}, sv) == sv + @test convert(AbstractArray{Int}, sv) === sv + sm = SMatrix{2,2}(1,2,3,4) + @test @inferred(convert(AbstractArray{Float64,2}, sm)) isa SMatrix{2,2,Float64} + @test convert(AbstractArray{Float64,2}, sm) == sm + @test convert(AbstractArray{Int,2}, sm) === sm + mv = MVector(1, 2, 3) + @test @inferred(convert(AbstractArray{Float64}, mv)) isa MVector{3,Float64} + @test @inferred(convert(AbstractVector{Float64}, mv)) isa MVector{3,Float64} + @test convert(AbstractArray{Float64}, mv) == mv + @test convert(AbstractArray{Int}, mv) === mv + mm = MMatrix{2, 2}(1, 2, 3, 4) + @test @inferred(convert(AbstractArray{Float64,2}, mm)) isa MMatrix{2,2,Float64} + @test convert(AbstractArray{Float64,2}, mm) == mm + @test convert(AbstractArray{Int,2}, mm) === mm + + # Test some of the types in StaticMatrixLike + sym = Symmetric(SA[1 2; 2 3]) + @test @inferred(convert(AbstractArray{Float64}, sym)) isa Symmetric{Float64,SMatrix{2,2,Float64,4}} + @test @inferred(convert(AbstractArray{Float64,2}, sym)) isa Symmetric{Float64,SMatrix{2,2,Float64,4}} + @test convert(AbstractArray{Float64}, sym) == sym + her = Hermitian(SA[1 2+im; 2-im 3]) + @test @inferred(convert(AbstractArray{ComplexF64}, her)) isa Hermitian{ComplexF64,SMatrix{2,2,ComplexF64,4}} + @test convert(AbstractArray{ComplexF64}, her) == her + diag = Diagonal(SVector(1,2)) + @test @inferred(convert(AbstractArray{Float64}, diag)) isa Diagonal{Float64,SVector{2,Float64}} + @test convert(AbstractArray{Float64}, diag) == diag + # The following cases currently convert the SMatrix into an MMatrix, because + # the constructor in Base invokes `similar`, rather than `convert`, on the static array + trans = Transpose(SVector(1,2)) + @test_broken @inferred(convert(AbstractArray{Float64}, trans)) isa Transpose{Float64,SVector{2,Float64}} + adj = Adjoint(SVector(1,2)) + @test_broken @inferred(convert(AbstractArray{Float64}, adj)) isa Adjoint{Float64,SVector{2,Float64}} + uptri = UpperTriangular(SA[1 2; 0 3]) + @test_broken @inferred(convert(AbstractArray{Float64}, uptri)) isa UpperTriangular{Float64,SMatrix{2,2,Float64,4}} + lotri = LowerTriangular(SA[1 0; 2 3]) + @test_broken @inferred(convert(AbstractArray{Float64}, lotri)) isa LowerTriangular{Float64,SMatrix{2,2,Float64,4}} + unituptri = UnitUpperTriangular(SA[1 2; 0 1]) + @test_broken @inferred(convert(AbstractArray{Float64}, unituptri)) isa UnitUpperTriangular{Float64,SMatrix{2,2,Float64,4}} + unitlotri = UnitLowerTriangular(SA[1 0; 2 1]) + @test_broken @inferred(convert(AbstractArray{Float64}, unitlotri)) isa UnitLowerTriangular{Float64,SMatrix{2,2,Float64,4}} + end end @testset "vcat() and hcat()" begin @@ -191,4 +240,3 @@ end @test @inferred(vcat(A, B)) === SMatrix{4, 2}([Matrix(A); Matrix(B)]) end end -