Skip to content

Commit 5e3f074

Browse files
committed
Provides rudimentary interconversions between special matrix types
convert() now interconverts Diagonal, Bidiagonal, SymTridiagonal, Triangular and Matrix using naïve methods. Moves convert() out of diagonal.jl
1 parent a17879e commit 5e3f074

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

base/linalg/diagonal.jl

-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ Diagonal(A::Matrix) = Diagonal(diag(A))
88
size(D::Diagonal) = (length(D.diag),length(D.diag))
99
size(D::Diagonal,d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(D.diag) : 1)
1010

11-
convert{T}(::Type{Matrix{T}}, D::Diagonal{T}) = diagm(D.diag)
12-
convert{T}(::Type{SymTridiagonal{T}}, D::Diagonal{T}) = SymTridiagonal(D.diag,zeros(T,length(D.diag)-1))
13-
convert{T}(::Type{Tridiagonal{T}}, D::Diagonal{T}) = Tridiagonal(zeros(T,length(D.diag)-1),D.diag,zeros(T,length(D.diag)-1))
14-
1511
full(D::Diagonal) = diagm(D.diag)
1612
getindex(D::Diagonal, i::Integer, j::Integer) = i == j ? D.diag[i] : zero(eltype(D.diag))
1713

base/linalg/special.jl

+69
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,74 @@
11
#Methods operating on different special matrix types
22

3+
#Interconversion between special matrix types
4+
import Base.convert
5+
convert{T}(::Type{Bidiagonal}, A::Diagonal{T})=Bidiagonal(A.diag, zeros(T, size(A.diag,1)-1), true)
6+
convert{T}(::Type{SymTridiagonal}, A::Diagonal{T})=SymTridiagonal(A.diag, zeros(T, size(A.diag,1)-1))
7+
convert{T}(::Type{Tridiagonal}, A::Diagonal{T})=Tridiagonal(zeros(T, size(A.diag,1)-1), A.diag, zeros(T, size(A.diag,1)-1))
8+
convert(::Type{Triangular}, A::Union(Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal))=Triangular(full(A))
9+
convert(::Type{Matrix}, D::Diagonal) = diagm(D.diag)
10+
11+
function convert(::Type{Diagonal}, A::Union(Bidiagonal, SymTridiagonal))
12+
all(A.ev .== 0) || throw(ArgumentError("Matrix cannot be represented as Diagonal"))
13+
Diagonal(A.dv)
14+
end
15+
16+
function convert(::Type{SymTridiagonal}, A::Bidiagonal)
17+
all(A.ev .== 0) || throw(ArgumentError("Matrix cannot be represented as SymTridiagonal"))
18+
SymTridiagonal(A.dv, A.ev)
19+
end
20+
21+
convert{T}(::Type{Tridiagonal}, A::Bidiagonal{T})=Tridiagonal(A.isupper?zeros(T, size(A.dv,1)-1):A.ev, A.dv, A.isupper?A.ev:zeros(T, size(A.dv,1)-1))
22+
23+
function convert(::Type{Bidiagonal}, A::SymTridiagonal)
24+
all(A.ev .== 0) || throw(ArgumentError("Matrix cannot be represented as Bidiagonal"))
25+
Bidiagonal(A.dv, A.ev, true)
26+
end
27+
28+
function convert(::Type{Diagonal}, A::Tridiagonal)
29+
all(A.dl .== 0) && all(A.du .== 0) || throw(ArgumentError("Matrix cannot be represented as Diagonal"))
30+
Diagonal(A.d)
31+
end
32+
33+
function convert(::Type{Bidiagonal}, A::Tridiagonal)
34+
if all(A.dl .== 0) return Bidiagonal(A.d, A.du, true)
35+
elseif all(A.du .== 0) return Bidiagonal(A.d, A.dl, true)
36+
else throw(ArgumentError("Matrix cannot be represented as Bidiagonal"))
37+
end
38+
end
39+
40+
function convert(::Type{SymTridiagonal}, A::Tridiagonal)
41+
all(A.dl .== A.du) || throw(ArgumentError("Matrix cannot be represented as SymTridiagonal"))
42+
SymTridiagonal(A.d, A.dl)
43+
end
44+
45+
function convert(::Type{Diagonal}, A::Triangular)
46+
full(A) == diagm(diag(A)) || throw(ArgumentError("Matrix cannot be represented as Diagonal"))
47+
Diagonal(diag(A))
48+
end
49+
50+
function convert(::Type{Bidiagonal}, A::Triangular)
51+
fA = full(A)
52+
if fA == diagm(diag(A)) + diagm(diag(fA, 1), 1)
53+
return Bidiagonal(diag(A), diag(fA,1), true)
54+
elseif fA == diagm(diag(A)) + diagm(diag(fA, -1), -1)
55+
return Bidiagonal(diag(A), diag(fA,-1), true)
56+
else
57+
throw(ArgumentError("Matrix cannot be represented as Bidiagonal"))
58+
end
59+
end
60+
61+
convert(::Type{SymTridiagonal}, A::Triangular) = convert(SymTridiagonal, convert(Tridiagonal, A))
62+
63+
function convert(::Type{Tridiagonal}, A::Triangular)
64+
fA = full(A)
65+
if fA == diagm(diag(A)) + diagm(diag(fA, 1), 1) + diagm(diag(fA, -1), -1)
66+
return Tridiagonal(diag(fA, -1), diag(A), diag(fA,1))
67+
else
68+
throw(ArgumentError("Matrix cannot be represented as Tridiagonal"))
69+
end
70+
end
71+
372
#Constructs two method definitions taking into account (assumed) commutativity
473
# e.g. @commutative f{S,T}(x::S, y::T) = x+y is the same is defining
574
# f{S,T}(x::S, y::T) = x+y

test/linalg.jl

+35
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,41 @@ for relty in (Float16, Float32, Float64, BigFloat), elty in (relty, Complex{relt
718718
end
719719
end
720720

721+
#Test interconversion between special matrix types
722+
using Base.Test
723+
724+
N=12
725+
A=Diagonal([1:N]*1.0)
726+
for newtype in [Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal, Triangular, Matrix]
727+
@test full(convert(newtype, A)) == full(A)
728+
end
729+
730+
for isupper in (true, false)
731+
A=Bidiagonal([1:N]*1.0, [1:N-1]*1.0, isupper)
732+
for newtype in [Bidiagonal, Tridiagonal, Triangular, Matrix]
733+
@test full(convert(newtype, A)) == full(A)
734+
end
735+
A=Bidiagonal([1:N]*1.0, [1:N-1]*0.0, isupper) #morally Diagonal
736+
for newtype in [Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal, Triangular, Matrix]
737+
@test full(convert(newtype, A)) == full(A)
738+
end
739+
end
740+
741+
A=SymTridiagonal([1:N]*1.0, [1:N-1]*1.0)
742+
for newtype in [Tridiagonal, Matrix]
743+
@test full(convert(newtype, A)) == full(A)
744+
end
745+
746+
A=Tridiagonal([1:N-1]*0.0, [1:N]*1.0, [1:N-1]*0.0) #morally Diagonal
747+
for newtype in [Diagonal, Bidiagonal, SymTridiagonal, Triangular, Matrix]
748+
@test full(convert(newtype, A)) == full(A)
749+
end
750+
751+
A=Triangular(full(Diagonal([1:N]*1.0))) #morally Diagonal
752+
for newtype in [Diagonal, Bidiagonal, SymTridiagonal, Triangular, Matrix]
753+
@test full(convert(newtype, A)) == full(A)
754+
end
755+
721756
# Test gglse
722757
for elty in (Float32, Float64, Complex64, Complex128)
723758
A = convert(Array{elty, 2}, [1 1 1 1; 1 3 1 1; 1 -1 3 1; 1 1 1 3; 1 1 1 -1])

0 commit comments

Comments
 (0)