diff --git a/src/generics.jl b/src/generics.jl index 0160558..8613923 100644 --- a/src/generics.jl +++ b/src/generics.jl @@ -1,5 +1,9 @@ # Generic functions (on top of the type-specific implementations) +## constructors +AbstractPDMat(A::AbstractPDMat) = A +AbstractPDMat(A::AbstractMatrix) = PDMat(A) + ## arithmetics pdadd!(r::Matrix, a::Matrix, b::AbstractPDMat{T}) where {T<:Real} = pdadd!(r, a, b, one(T)) diff --git a/src/pdiagmat.jl b/src/pdiagmat.jl index b9f78fa..9bc0602 100644 --- a/src/pdiagmat.jl +++ b/src/pdiagmat.jl @@ -8,6 +8,10 @@ end PDiagMat(v::AbstractVector{<:Real}) = PDiagMat{eltype(v),typeof(v)}(length(v), v) +AbstractPDMat(A::Diagonal{<:Real}) = PDiagMat(A.diag) +AbstractPDMat(A::Symmetric{<:Real,<:Diagonal{<:Real}}) = PDiagMat(A.data.diag) +AbstractPDMat(A::Hermitian{<:Real,<:Diagonal{<:Real}}) = PDiagMat(A.data.diag) + ### Conversion Base.convert(::Type{PDiagMat{T}}, a::PDiagMat) where {T<:Real} = PDiagMat(convert(AbstractArray{T}, a.diag)) Base.convert(::Type{AbstractArray{T}}, a::PDiagMat) where {T<:Real} = convert(PDiagMat{T}, a) diff --git a/src/pdmat.jl b/src/pdmat.jl index f4734dc..e543ee9 100644 --- a/src/pdmat.jl +++ b/src/pdmat.jl @@ -19,6 +19,8 @@ end PDMat(mat::AbstractMatrix) = PDMat(mat, cholesky(mat)) PDMat(fac::Cholesky) = PDMat(AbstractMatrix(fac), fac) +AbstractPDMat(A::Cholesky) = PDMat(A) + ### Conversion Base.convert(::Type{PDMat{T}}, a::PDMat) where {T<:Real} = PDMat(convert(AbstractArray{T}, a.mat)) Base.convert(::Type{AbstractArray{T}}, a::PDMat) where {T<:Real} = convert(PDMat{T}, a) diff --git a/src/pdsparsemat.jl b/src/pdsparsemat.jl index 7c2c433..95ac63a 100644 --- a/src/pdsparsemat.jl +++ b/src/pdsparsemat.jl @@ -18,7 +18,10 @@ function PDSparseMat(mat::AbstractSparseMatrix,chol::CholTypeSparse) end PDSparseMat(mat::SparseMatrixCSC) = PDSparseMat(mat, cholesky(mat)) -PDSparseMat(fac::CholTypeSparse) = PDSparseMat(sparse(fac) |> x -> x*x', fac) +PDSparseMat(fac::CholTypeSparse) = PDSparseMat(sparse(fac), fac) + +AbstractPDMat(A::SparseMatrixCSC) = PDSparseMat(A) +AbstractPDMat(A::CholTypeSparse) = PDSparseMat(A) ### Conversion Base.convert(::Type{PDSparseMat{T}}, a::PDSparseMat) where {T<:Real} = PDSparseMat(convert(SparseMatrixCSC{T}, a.mat)) diff --git a/test/pdmtypes.jl b/test/pdmtypes.jl index 33ded7e..286288a 100644 --- a/test/pdmtypes.jl +++ b/test/pdmtypes.jl @@ -121,4 +121,42 @@ using Test @test Matrix(M) ≈ A end end + + @testset "AbstractPDMat constructors (#136)" begin + x = rand(10, 10) + A = x' * x + I + + M = @inferred AbstractPDMat(A) + @test M isa PDMat + @test Matrix(M) ≈ A + + M = @inferred AbstractPDMat(cholesky(A)) + @test M isa PDMat + @test Matrix(M) ≈ A + + M = @inferred AbstractPDMat(Diagonal(A)) + @test M isa PDiagMat + @test Matrix(M) ≈ Diagonal(A) + + M = @inferred AbstractPDMat(Symmetric(Diagonal(A))) + @test M isa PDiagMat + @test Matrix(M) ≈ Diagonal(A) + + M = @inferred AbstractPDMat(Hermitian(Diagonal(A))) + @test M isa PDiagMat + @test Matrix(M) ≈ Diagonal(A) + + M = @inferred AbstractPDMat(sparse(A)) + @test M isa PDSparseMat + @test Matrix(M) ≈ A + + if VERSION < v"1.6" + # inference fails e.g. on Julia 1.0 + M = AbstractPDMat(cholesky(sparse(A))) + else + M = @inferred AbstractPDMat(cholesky(sparse(A))) + end + @test M isa PDSparseMat + @test Matrix(M) ≈ A + end end diff --git a/test/testutils.jl b/test/testutils.jl index 9b194c2..7571583 100644 --- a/test/testutils.jl +++ b/test/testutils.jl @@ -91,6 +91,13 @@ function pdtest_basics(C, Cmat::Matrix, d::Int, verbose::Int) _pdt(verbose, "ishermitian") @test ishermitian(C) + + _pdt(verbose, "AbstractPDMat") + M = AbstractPDMat(C) + @test M isa AbstractPDMat + if C isa AbstractPDMat + @test M === C + end end