From aae6737e348c97d0412b661ddedcbfdb5e3db5bc Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 27 Jul 2016 13:23:39 -0700 Subject: [PATCH] Make conversion from Bidiagonal to (Upper|Lower)Triangular preserve Bidiagional storage structure. Add equivalent methods for conversion from Bidiagonal to Unit(Upper|Lower)Triangular. Group methods and revise error messages. Test. --- base/linalg/special.jl | 35 +++++++++++++++++++++++++++++------ test/linalg/special.jl | 25 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/base/linalg/special.jl b/base/linalg/special.jl index f70d67130807be..a43b979cb0e38c 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -6,14 +6,37 @@ convert{T}(::Type{Bidiagonal}, A::Diagonal{T})=Bidiagonal(A.diag, zeros(T, size(A.diag,1)-1), true) convert{T}(::Type{SymTridiagonal}, A::Diagonal{T})=SymTridiagonal(A.diag, zeros(T, size(A.diag,1)-1)) convert{T}(::Type{Tridiagonal}, A::Diagonal{T})=Tridiagonal(zeros(T, size(A.diag,1)-1), A.diag, zeros(T, size(A.diag,1)-1)) -convert(::Type{LowerTriangular}, A::Bidiagonal) = !A.isupper ? LowerTriangular(full(A)) : throw(ArgumentError("Bidiagonal matrix must have lower off diagonal to be converted to LowerTriangular")) -convert(::Type{UpperTriangular}, A::Bidiagonal) = A.isupper ? UpperTriangular(full(A)) : throw(ArgumentError("Bidiagonal matrix must have upper off diagonal to be converted to UpperTriangular")) -function convert(::Type{UnitUpperTriangular}, A::Diagonal) - if !all(A.diag .== one(eltype(A))) - throw(ArgumentError("matrix cannot be represented as UnitUpperTriangular")) +# methods for conversion from Bidiagonal to [Unit](Upper|Lower)Triangular +function convert(::Type{LowerTriangular}, A::Bidiagonal) + if A.isupper + throw(ArgumentError("upper Bidiagonal matrices cannot be converted to LowerTriangular")) + end + LowerTriangular(A) +end +function convert(::Type{UpperTriangular}, A::Bidiagonal) + if !A.isupper + throw(ArgumentError("lower Bidiagonal matrices cannot be converted to UpperTriangular")) end - UnitUpperTriangular(full(A)) + UpperTriangular(A) +end +function convert(::Type{UnitLowerTriangular}, A::Bidiagonal) + if A.isupper + throw(ArgumentError("upper Bidiagonal matrices cannot be converted to UnitLowerTriangular")) + elseif !all(A.ev .== one(eltype(A))) + throw(ArgumentError(string("Bidiagonal matrices with non-one entries on the ", + "diagonal cannot be converted to UnitLowerTriangular"))) + end + UnitLowerTriangular(A) +end +function convert(::Type{UnitUpperTriangular}, A::Bidiagonal) + if !A.isupper + throw(ArgumentError("lower Bidiagonal matrices cannot be converted to UnitUpperTriangular")) + elseif !all(A.ev . == one(eltype(A))) + throw(ArgumentError(string("Bidiagonal matrices with non-one entries on the ", + "diagonal cannot be converted to UnitUpperTriangular"))) + end + UnitUpperTriangular(A) end function convert(::Type{UnitLowerTriangular}, A::Diagonal) diff --git a/test/linalg/special.jl b/test/linalg/special.jl index 89ddde5ee4b007..9ff55d67bfdba8 100644 --- a/test/linalg/special.jl +++ b/test/linalg/special.jl @@ -128,3 +128,28 @@ for typ in [UpperTriangular,LowerTriangular,Base.LinAlg.UnitUpperTriangular,Base @test Base.LinAlg.A_mul_Bc(atri,qrb[:Q]) ≈ full(atri) * qrb[:Q]' @test Base.LinAlg.A_mul_Bc!(copy(atri),qrb[:Q]) ≈ full(atri) * qrb[:Q]' end + +# Test conversion from Bidiagonal to <:AbstractTriangular +let + lowerbidiagmat = Bidiagonal(rand(3), rand(2), false) + upperbidiagmat = Bidiagonal(rand(3), rand(2), true) + unitlowerbidiagmat = Bidiagonal(ones(3), rand(2), false) + unitupperbidiagmat = Bidiagonal(ones(3), rand(2), true) + # test that conversion from upper(lower) bidiagonal to lower(upper) [unit]triangular throws + @test_throws ArgumentError convert(UpperTriangular, unitlowerbidiagmat) + @test_throws ArgumentError convert(LowerTriangular, unitupperbidiagmat) + @test_throws ArgumentError convert(UnitUpperTriangular, unitlowerbidiagmat) + @test_throws ArgumentError convert(UnitLowerTriangular, unitupperbidiagmat) + # test that conversion from non-unit bidiag to unit triangular throws + @test_throws ArgumentError convert(UnitUpperTriangular, upperbidiagmat) + @test_throws ArgumentError convert(UnitLowerTriangular, lowerbidiagmat) + # test that conversion from bidiagonal to triangular preserves bidiagonal storage structure + @test typeof(convert(UpperTriangular, upperbidiagmat)) == + UpperTriangular{eltype(upperbidiagmat),Bidiagonal{eltype(upperbidiagmat)}} + @test typeof(convert(LowerTriangular, lowerbidiagmat)) == + LowerTriangular{eltype(lowerbidiagmat),Bidiagonal{eltype(lowerbidiagmat)}} + @test typeof(convert(Base.LinAlg.UnitUpperTriangular, unitupperbidiagmat)) == + Base.LinAlg.UnitUpperTriangular{eltype(unitupperbidiagmat),Bidiagonal{eltype(unitupperbidiagmat)}} + @test typeof(convert(Base.LinAlg.UnitLowerTriangular, unitlowerbidiagmat)) == + Base.LinAlg.UnitLowerTriangular{eltype(unitlowerbidiagmat),Bidiagonal{eltype(unitlowerbidiagmat)}} +end