Skip to content

Commit

Permalink
Fix Matrix on diagonal and triangular matrices for types without zero
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Jun 12, 2020
1 parent 6e7bc68 commit 77e5677
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 10 deletions.
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/src/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,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_with_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
Expand Down
6 changes: 3 additions & 3 deletions stdlib/LinearAlgebra/src/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,11 @@ function diagm_size(size::Tuple{Int,Int}, kv::Pair{<:Integer,<:AbstractVector}..
(m mmax && n nmax) || throw(DimensionMismatch("invalid size=$size"))
return m, n
end
# For some type `T`, `zero(T)` is not a `T` and `zeros(T, ...)` fails.
promote_with_zero(T::Type) = promote_type(T, typeof(zero(T)))
function diagm_container(size, kv::Pair{<:Integer,<:AbstractVector}...)
T = promote_type(map(x -> eltype(x.second), kv)...)
# For some type `T`, `zero(T)` is not a `T` and `zeros(T, ...)` fails.
U = promote_type(T, typeof(zero(T)))
return zeros(U, diagm_size(size, kv...)...)
return zeros(promote_with_zero(T), diagm_size(size, kv...)...)
end
diagm_container(size, kv::Pair{<:Integer,<:BitVector}...) =
falses(diagm_size(size, kv...)...)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/src/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular,
Anew = convert(AbstractMatrix{T}, A.data)
$t(Anew)
end
Matrix(A::$t{T}) where {T} = Matrix{T}(A)
Matrix(A::$t{T}) where {T} = Matrix{promote_with_zero(T)}(A)

size(A::$t, d) = size(A.data, d)
size(A::$t) = size(A.data)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/src/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function Matrix{T}(M::SymTridiagonal) where T
end
return Mf
end
Matrix(M::SymTridiagonal{T}) where {T} = Matrix{T}(M)
Matrix(M::SymTridiagonal{T}) where {T} = Matrix{promote_with_zero(T)}(M)
Array(M::SymTridiagonal) = Matrix(M)

size(A::SymTridiagonal) = (length(A.dv), length(A.dv))
Expand Down Expand Up @@ -579,7 +579,7 @@ function Matrix{T}(M::Tridiagonal{T}) where T
end
A
end
Matrix(M::Tridiagonal{T}) where {T} = Matrix{T}(M)
Matrix(M::Tridiagonal{T}) where {T} = Matrix{promote_with_zero(T)}(M)
Array(M::Tridiagonal) = Matrix(M)

# For M<:Tridiagonal, similar(M[, neweltype]) should yield a Tridiagonal matrix.
Expand Down
21 changes: 18 additions & 3 deletions stdlib/LinearAlgebra/test/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -943,11 +943,26 @@ struct TypeWithoutZero end
Base.zero(::Type{TypeWithoutZero}) = TypeWithZero()
struct TypeWithZero end
Base.promote_rule(::Type{TypeWithoutZero}, ::Type{TypeWithZero}) = TypeWithZero
Base.zero(::Type{<:Union{TypeWithoutZero, TypeWithZero}}) = TypeWithZero()
Base.convert(::Type{TypeWithZero}, ::TypeWithoutZero) = TypeWithZero()
Base.zero(::Union{TypeWithZero, Type{<:Union{TypeWithoutZero, TypeWithZero}}}) = TypeWithZero()
Base.:+(x::TypeWithZero, ::TypeWithoutZero) = x

@testset "diagm for type with no zero" begin
@test diagm(0 => [TypeWithoutZero()]) isa Matrix{TypeWithZero}
@testset "diagm and Matrix for type with no zero" begin
x = TypeWithoutZero()
@test (@inferred diagm(0 => [x])) isa Matrix{TypeWithZero}
diag = [x, x, x]
offdiag = [x, x]
X = [x x
x x]
for A in [
Bidiagonal(diag, offdiag, :U),
Tridiagonal(offdiag, diag, offdiag),
SymTridiagonal(diag, offdiag),
LowerTriangular(X),
UpperTriangular(X)
]
@test (@inferred Matrix(A)) isa Matrix{TypeWithZero}
end
end

end # module TestDense

0 comments on commit 77e5677

Please sign in to comment.