From 2d6f408e979c4c7ea721339de9546ae2fa81e52f 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 | 34 ++++++++++++++++++++++++++++++++-- test/linalg/special.jl | 25 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/base/linalg/special.jl b/base/linalg/special.jl index f70d67130807b..cf6f17702489c 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -6,8 +6,38 @@ 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")) + +# 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 + 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.dv .== 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.dv .== 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{UnitUpperTriangular}, A::Diagonal) if !all(A.diag .== one(eltype(A))) diff --git a/test/linalg/special.jl b/test/linalg/special.jl index 89ddde5ee4b00..d61c340081ae4 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(Base.LinAlg.UnitUpperTriangular, unitlowerbidiagmat) + @test_throws ArgumentError convert(Base.LinAlg.UnitLowerTriangular, unitupperbidiagmat) + # test that conversion from non-unit bidiag to unit triangular throws + @test_throws ArgumentError convert(Base.LinAlg.UnitUpperTriangular, upperbidiagmat) + @test_throws ArgumentError convert(Base.LinAlg.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