Skip to content

Commit

Permalink
Make conversion from Bidiagonal to (Upper|Lower)Triangular preserve B…
Browse files Browse the repository at this point in the history
…idiagional storage structure. Add equivalent methods for conversion from Bidiagonal to Unit(Upper|Lower)Triangular. Group methods and revise error messages. Test.
  • Loading branch information
Sacha0 committed Jul 27, 2016
1 parent d0a378d commit 0f76ed1
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
35 changes: 33 additions & 2 deletions base/linalg/special.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,45 @@
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.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{UnitUpperTriangular}, A::Diagonal)
if !all(A.diag .== one(eltype(A)))
throw(ArgumentError("matrix cannot be represented as UnitUpperTriangular"))
end
UnitUpperTriangular(full(A))
UnitUpperTriangular(A)
end

function convert(::Type{UnitLowerTriangular}, A::Diagonal)
Expand Down
25 changes: 25 additions & 0 deletions test/linalg/special.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 0f76ed1

Please sign in to comment.