diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index dfcbec69c6de2..317ed15af770c 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -180,7 +180,7 @@ function Matrix{T}(A::Bidiagonal) where T B[n,n] = A.dv[n] return B end -Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A) +Matrix(A::Bidiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(A) Array(A::Bidiagonal) = Matrix(A) promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = @isdefined(T) && @isdefined(S) ? Matrix{promote_type(T,S)} : Matrix diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index ffcd9e64e0752..249010adb4e5c 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -257,6 +257,8 @@ Vector `kv.second` will be placed on the `kv.first` diagonal. By default the matrix is square and its size is inferred from `kv`, but a non-square size `m`×`n` (padded with zeros as needed) can be specified by passing `m,n` as the first arguments. +For repeated diagonal indices `kv.first` the values in the corresponding +vectors `kv.second` will be added. `diagm` constructs a full matrix; if you want storage-efficient versions with fast arithmetic, see [`Diagonal`](@ref), [`Bidiagonal`](@ref) @@ -277,6 +279,13 @@ julia> diagm(1 => [1,2,3], -1 => [4,5]) 4 0 2 0 0 5 0 3 0 0 0 0 + +julia> diagm(1 => [1,2,3], 1 => [1,2,3]) +4×4 Matrix{Int64}: + 0 2 0 0 + 0 0 4 0 + 0 0 0 6 + 0 0 0 0 ``` """ diagm(kv::Pair{<:Integer,<:AbstractVector}...) = _diagm(nothing, kv...) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 11f3fff9cb3e2..5d17049cfa4e1 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -77,8 +77,8 @@ Diagonal{T}(D::Diagonal{T}) where {T} = D Diagonal{T}(D::Diagonal) where {T} = Diagonal{T}(D.diag) AbstractMatrix{T}(D::Diagonal) where {T} = Diagonal{T}(D) -Matrix(D::Diagonal{T}) where {T} = Matrix{T}(D) -Array(D::Diagonal{T}) where {T} = Matrix{T}(D) +Matrix(D::Diagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(D) +Array(D::Diagonal{T}) where {T} = Matrix(D) function Matrix{T}(D::Diagonal) where {T} n = size(D, 1) B = zeros(T, n, n) diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 4b1d3add5df5b..e5c31856d3f0a 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -134,7 +134,7 @@ function Matrix{T}(M::SymTridiagonal) where T Mf[n,n] = symmetric(M.dv[n], :U) return Mf end -Matrix(M::SymTridiagonal{T}) where {T} = Matrix{T}(M) +Matrix(M::SymTridiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(M) Array(M::SymTridiagonal) = Matrix(M) size(A::SymTridiagonal) = (length(A.dv), length(A.dv)) @@ -583,7 +583,7 @@ function Matrix{T}(M::Tridiagonal) where {T} A[n,n] = M.d[n] A end -Matrix(M::Tridiagonal{T}) where {T} = Matrix{T}(M) +Matrix(M::Tridiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(M) Array(M::Tridiagonal) = Matrix(M) similar(M::Tridiagonal, ::Type{T}) where {T} = Tridiagonal(similar(M.dl, T), similar(M.d, T), similar(M.du, T)) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 9b094c267d41b..234f9f472557b 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -104,6 +104,28 @@ Random.seed!(1) @test LowerTriangular(C) == LowerTriangular(Cdense) end end + + @testset "Matrix constructor for !isa(zero(T), T)" begin + # the following models JuMP.jl's VariableRef and AffExpr, resp. + struct TypeWithoutZero end + struct TypeWithZero end + Base.promote_rule(::Type{TypeWithoutZero}, ::Type{TypeWithZero}) = TypeWithZero + Base.convert(::Type{TypeWithZero}, ::TypeWithoutZero) = TypeWithZero() + Base.zero(::Type{<:Union{TypeWithoutZero, TypeWithZero}}) = TypeWithZero() + LinearAlgebra.symmetric(::TypeWithoutZero, ::Symbol) = TypeWithoutZero() + Base.transpose(::TypeWithoutZero) = TypeWithoutZero() + d = fill(TypeWithoutZero(), 3) + du = fill(TypeWithoutZero(), 2) + dl = fill(TypeWithoutZero(), 2) + D = Diagonal(d) + Bu = Bidiagonal(d, du, :U) + Bl = Bidiagonal(d, dl, :L) + Tri = Tridiagonal(dl, d, du) + Sym = SymTridiagonal(d, dl) + for M in (D, Bu, Bl, Tri, Sym) + @test Matrix(M) == zeros(TypeWithZero, 3, 3) + end + end end @testset "Binary ops among special types" begin