Skip to content

Commit 0805c3d

Browse files
committed
Merge pull request #9779 from JuliaLang/anj/triangle
Redesign of triangular matrix types
2 parents 9997018 + e642034 commit 0805c3d

19 files changed

+787
-393
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ Library improvements
154154

155155
* copy(DArray) will now make a copy of the DArray ([#9745])
156156

157+
* Split `Triangular` type into `UpperTriangular`, `LowerTriangular`, `UnitUpperTriagular` and `UnitLowerTriangular` ([#9779])
158+
157159
Deprecated or removed
158160
---------------------
159161

base/exports.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export
6262
IOBuffer,
6363
IOStream,
6464
LocalProcess,
65+
LowerTriangular,
6566
MathConst,
6667
Matrix,
6768
MergeSort,
@@ -108,9 +109,9 @@ export
108109
SymTridiagonal,
109110
Timer,
110111
TmStruct,
111-
Triangular,
112112
Tridiagonal,
113113
UnitRange,
114+
UpperTriangular,
114115
UTF16String,
115116
UTF32String,
116117
Val,

base/linalg.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export
3030
SVD,
3131
Hermitian,
3232
Symmetric,
33-
Triangular,
33+
LowerTriangular,
34+
UpperTriangular,
3435
Diagonal,
3536
UniformScaling,
3637

base/linalg/bidiag.jl

+6-7
Original file line numberDiff line numberDiff line change
@@ -114,24 +114,23 @@ end
114114
/(A::Bidiagonal, B::Number) = Bidiagonal(A.dv/B, A.ev/B, A.isupper)
115115
==(A::Bidiagonal, B::Bidiagonal) = (A.dv==B.dv) && (A.ev==B.ev) && (A.isupper==B.isupper)
116116

117-
SpecialMatrix = Union(Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal, Triangular)
117+
SpecialMatrix = Union(Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal, TriangularUnion)
118118
*(A::SpecialMatrix, B::SpecialMatrix)=full(A)*full(B)
119119

120120
#Generic multiplication
121121
for func in (:*, :Ac_mul_B, :A_mul_Bc, :/, :A_rdiv_Bc)
122122
@eval begin
123123
($func){T}(A::Bidiagonal{T}, B::AbstractVector{T}) = ($func)(full(A), B)
124-
#($func){T}(A::AbstractArray{T}, B::Triangular{T}) = ($func)(full(A), B)
125124
end
126125
end
127126

128127

129128
#Linear solvers
130-
A_ldiv_B!(A::Union(Bidiagonal, Triangular), b::AbstractVector) = naivesub!(A, b)
131-
At_ldiv_B!(A::Union(Bidiagonal, Triangular), b::AbstractVector) = naivesub!(transpose(A), b)
132-
Ac_ldiv_B!(A::Union(Bidiagonal, Triangular), b::AbstractVector) = naivesub!(ctranspose(A), b)
129+
A_ldiv_B!(A::Union(Bidiagonal, TriangularUnion), b::AbstractVector) = naivesub!(A, b)
130+
At_ldiv_B!(A::Union(Bidiagonal, TriangularUnion), b::AbstractVector) = naivesub!(transpose(A), b)
131+
Ac_ldiv_B!(A::Union(Bidiagonal, TriangularUnion), b::AbstractVector) = naivesub!(ctranspose(A), b)
133132
for func in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) @eval begin
134-
function ($func)(A::Union(Bidiagonal, Triangular), B::AbstractMatrix)
133+
function ($func)(A::Union(Bidiagonal, TriangularUnion), B::AbstractMatrix)
135134
tmp = similar(B[:,1])
136135
n = size(B, 1)
137136
for i = 1:size(B,2)
@@ -143,7 +142,7 @@ for func in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) @eval begin
143142
end
144143
end end
145144
for func in (:A_ldiv_Bt!, :Ac_ldiv_Bt!, :At_ldiv_Bt!) @eval begin
146-
function ($func)(A::Union(Bidiagonal, Triangular), B::AbstractMatrix)
145+
function ($func)(A::Union(Bidiagonal, TriangularUnion), B::AbstractMatrix)
147146
tmp = similar(B[:, 2])
148147
m, n = size(B)
149148
nm = n*m

base/linalg/cholesky.jl

+36-13
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,35 @@ immutable CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T}
1818
end
1919
CholeskyPivoted{T}(UL::AbstractMatrix{T}, uplo::Char, piv::Vector{BlasInt}, rank::BlasInt, tol::Real, info::BlasInt) = CholeskyPivoted{T,typeof(UL)}(UL, uplo, piv, rank, tol, info)
2020

21-
function chol!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol=:U)
21+
function chol!{T<:BlasFloat}(A::StridedMatrix{T})
22+
C, info = LAPACK.potrf!('U', A)
23+
return @assertposdef UpperTriangular(C) info
24+
end
25+
function chol!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol)
2226
C, info = LAPACK.potrf!(char_uplo(uplo), A)
23-
return @assertposdef Triangular{eltype(C),typeof(C),uplo,false}(C) info
27+
return @assertposdef uplo == :U ? UpperTriangular(C) : LowerTriangular(C) info
2428
end
2529

26-
function chol!{T}(A::AbstractMatrix{T}, uplo::Symbol=:U)
30+
function chol!{T}(A::AbstractMatrix{T})
31+
n = chksquare(A)
32+
@inbounds begin
33+
for k = 1:n
34+
for i = 1:k - 1
35+
A[k,k] -= A[i,k]'A[i,k]
36+
end
37+
A[k,k] = chol!(A[k,k], uplo)
38+
AkkInv = inv(A[k,k])
39+
for j = k + 1:n
40+
for i = 1:k - 1
41+
A[k,j] -= A[i,k]'A[i,j]
42+
end
43+
A[k,j] = A[k,k]'\A[k,j]
44+
end
45+
end
46+
end
47+
return UpperTriangular(A)
48+
end
49+
function chol!{T}(A::AbstractMatrix{T}, uplo::Symbol)
2750
n = chksquare(A)
2851
@inbounds begin
2952
if uplo == :L
@@ -58,7 +81,7 @@ function chol!{T}(A::AbstractMatrix{T}, uplo::Symbol=:U)
5881
throw(ArgumentError("uplo must be either :U or :L but was $(uplo)"))
5982
end
6083
end
61-
return Triangular(A, uplo, false)
84+
return uplo == :U ? UpperTriangular(A) : LowerTriangular(A)
6285
end
6386

6487
function cholfact!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol=:U; pivot=false, tol=0.0)
@@ -118,14 +141,14 @@ size(C::Union(Cholesky, CholeskyPivoted)) = size(C.UL)
118141
size(C::Union(Cholesky, CholeskyPivoted), d::Integer) = size(C.UL,d)
119142

120143
function getindex{T,S,UpLo}(C::Cholesky{T,S,UpLo}, d::Symbol)
121-
d == :U && return Triangular(UpLo == d ? C.UL : C.UL',:U)
122-
d == :L && return Triangular(UpLo == d ? C.UL : C.UL',:L)
123-
d == :UL && return Triangular(C.UL, UpLo)
144+
d == :U && return UpperTriangular(UpLo == d ? C.UL : C.UL')
145+
d == :L && return LowerTriangular(UpLo == d ? C.UL : C.UL')
146+
d == :UL && return UpLo == :U ? UpperTriangular(C.UL) : LowerTriangular(C.UL)
124147
throw(KeyError(d))
125148
end
126149
function getindex{T<:BlasFloat}(C::CholeskyPivoted{T}, d::Symbol)
127-
d == :U && return Triangular(symbol(C.uplo) == d ? C.UL : C.UL', :U)
128-
d == :L && return Triangular(symbol(C.uplo) == d ? C.UL : C.UL', :L)
150+
d == :U && return UpperTriangular(symbol(C.uplo) == d ? C.UL : C.UL')
151+
d == :L && return LowerTriangular(symbol(C.uplo) == d ? C.UL : C.UL')
129152
d == :p && return C.piv
130153
if d == :P
131154
n = size(C, 1)
@@ -142,8 +165,8 @@ show{T,S<:AbstractMatrix,UpLo}(io::IO, C::Cholesky{T,S,UpLo}) = (println("$(type
142165

143166
A_ldiv_B!{T<:BlasFloat,S<:AbstractMatrix}(C::Cholesky{T,S,:U}, B::StridedVecOrMat{T}) = LAPACK.potrs!('U', C.UL, B)
144167
A_ldiv_B!{T<:BlasFloat,S<:AbstractMatrix}(C::Cholesky{T,S,:L}, B::StridedVecOrMat{T}) = LAPACK.potrs!('L', C.UL, B)
145-
A_ldiv_B!{T,S<:AbstractMatrix}(C::Cholesky{T,S,:L}, B::StridedVecOrMat) = Ac_ldiv_B!(Triangular(C.UL, :L, false), A_ldiv_B!(Triangular(C.UL, :L, false), B))
146-
A_ldiv_B!{T,S<:AbstractMatrix}(C::Cholesky{T,S,:U}, B::StridedVecOrMat) = A_ldiv_B!(Triangular(C.UL, :U, false), Ac_ldiv_B!(Triangular(C.UL, :U, false), B))
168+
A_ldiv_B!{T,S<:AbstractMatrix}(C::Cholesky{T,S,:L}, B::StridedVecOrMat) = Ac_ldiv_B!(LowerTriangular(C.UL), A_ldiv_B!(LowerTriangular(C.UL), B))
169+
A_ldiv_B!{T,S<:AbstractMatrix}(C::Cholesky{T,S,:U}, B::StridedVecOrMat) = A_ldiv_B!(UpperTriangular(C.UL), Ac_ldiv_B!(UpperTriangular(C.UL), B))
147170

148171
function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedVector{T})
149172
chkfullrank(C)
@@ -161,8 +184,8 @@ function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedMatrix{T})
161184
end
162185
B
163186
end
164-
A_ldiv_B!(C::CholeskyPivoted, B::StridedVector) = C.uplo=='L' ? Ac_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), A_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), B[C.piv]))[invperm(C.piv)] : A_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), Ac_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), B[C.piv]))[invperm(C.piv)]
165-
A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) = C.uplo=='L' ? Ac_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), A_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), B[C.piv,:]))[invperm(C.piv),:] : A_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), Ac_ldiv_B!(Triangular(C.UL, symbol(C.uplo), false), B[C.piv,:]))[invperm(C.piv),:]
187+
A_ldiv_B!(C::CholeskyPivoted, B::StridedVector) = C.uplo=='L' ? Ac_ldiv_B!(LowerTriangular(C.UL), A_ldiv_B!(LowerTriangular(C.UL), B[C.piv]))[invperm(C.piv)] : A_ldiv_B!(UpperTriangular(C.UL), Ac_ldiv_B!(UpperTriangular(C.UL), B[C.piv]))[invperm(C.piv)]
188+
A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) = C.uplo=='L' ? Ac_ldiv_B!(LowerTriangular(C.UL), A_ldiv_B!(LowerTriangular(C.UL), B[C.piv,:]))[invperm(C.piv),:] : A_ldiv_B!(UpperTriangular(C.UL), Ac_ldiv_B!(UpperTriangular(C.UL), B[C.piv,:]))[invperm(C.piv),:]
166189

167190
function det{T,S,UpLo}(C::Cholesky{T,S,UpLo})
168191
dd = one(T)

base/linalg/dense.jl

+8-8
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,15 @@ function sqrtm{T<:Real}(A::StridedMatrix{T})
307307
issym(A) && return sqrtm(Symmetric(A))
308308
n = chksquare(A)
309309
SchurF = schurfact(complex(A))
310-
R = full(sqrtm(Triangular(SchurF[:T], :U, false)))
310+
R = full(sqrtm(UpperTriangular(SchurF[:T])))
311311
retmat = SchurF[:vectors]*R*SchurF[:vectors]'
312312
all(imag(retmat) .== 0) ? real(retmat) : retmat
313313
end
314314
function sqrtm{T<:Complex}(A::StridedMatrix{T})
315315
ishermitian(A) && return sqrtm(Hermitian(A))
316316
n = chksquare(A)
317317
SchurF = schurfact(A)
318-
R = full(sqrtm(Triangular(SchurF[:T], :U, false)))
318+
R = full(sqrtm(UpperTriangular(SchurF[:T])))
319319
SchurF[:vectors]*R*SchurF[:vectors]'
320320
end
321321
sqrtm(a::Number) = (b = sqrt(complex(a)); imag(b) == 0 ? real(b) : b)
@@ -325,9 +325,9 @@ function inv{S}(A::StridedMatrix{S})
325325
T = typeof(one(S)/one(S))
326326
Ac = convert(AbstractMatrix{T}, A)
327327
if istriu(Ac)
328-
Ai = inv(Triangular(A, :U, false))
328+
Ai = inv(UpperTriangular(A))
329329
elseif istril(Ac)
330-
Ai = inv(Triangular(A, :L, false))
330+
Ai = inv(LowerTriangular(A))
331331
else
332332
Ai = inv(lufact(Ac))
333333
end
@@ -377,7 +377,7 @@ function factorize{T}(A::Matrix{T})
377377
if utri1
378378
return Bidiagonal(diag(A), diag(A, -1), false)
379379
end
380-
return Triangular(A, :L)
380+
return LowerTriangular(A)
381381
end
382382
if utri
383383
return Bidiagonal(diag(A), diag(A, 1), true)
@@ -392,7 +392,7 @@ function factorize{T}(A::Matrix{T})
392392
end
393393
end
394394
if utri
395-
return Triangular(A, :U)
395+
return UpperTriangular(A)
396396
end
397397
if herm
398398
try
@@ -413,9 +413,9 @@ function (\)(A::StridedMatrix, B::StridedVecOrMat)
413413
m, n = size(A)
414414
if m == n
415415
if istril(A)
416-
return istriu(A) ? \(Diagonal(A),B) : \(Triangular(A, :L),B)
416+
return istriu(A) ? \(Diagonal(A),B) : \(LowerTriangular(A),B)
417417
end
418-
istriu(A) && return \(Triangular(A, :U),B)
418+
istriu(A) && return \(UpperTriangular(A),B)
419419
return \(lufact(A),B)
420420
end
421421
return qrfact(A,pivot=eltype(A)<:BlasFloat)\B

base/linalg/diagonal.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Diagonal(A::Matrix) = Diagonal(diag(A))
88
convert{T}(::Type{Diagonal{T}}, D::Diagonal{T}) = D
99
convert{T}(::Type{Diagonal{T}}, D::Diagonal) = Diagonal{T}(convert(Vector{T}, D.diag))
1010
convert{T}(::Type{AbstractMatrix{T}}, D::Diagonal) = convert(Diagonal{T}, D)
11-
convert{T}(::Type{Triangular}, A::Diagonal{T}) = Triangular{T, Diagonal{T}, :U, false}(A)
11+
convert{T}(::Type{UpperTriangular}, A::Diagonal{T}) = UpperTriangular(A)
12+
convert{T}(::Type{LowerTriangular}, A::Diagonal{T}) = LowerTriangular(A)
1213

1314
function similar{T}(D::Diagonal, ::Type{T}, d::(Int,Int))
1415
d[1] == d[2] || throw(ArgumentError("Diagonal matrix must be square"))

base/linalg/factorization.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ function A_mul_Bc!{T}(A::AbstractMatrix{T},Q::QRPackedQ{T})
274274
end
275275
A
276276
end
277-
A_mul_Bc(A::Triangular, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B)
277+
A_mul_Bc(A::TriangularUnion, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B)
278278
function A_mul_Bc{TA,TB}(A::AbstractArray{TA}, B::Union(QRCompactWYQ{TB},QRPackedQ{TB}))
279279
TAB = promote_type(TA,TB)
280280
A_mul_Bc!(size(A,2)==size(B.factors,1) ? (TA == TAB ? copy(A) : convert(AbstractMatrix{TAB}, A)) :
@@ -284,8 +284,8 @@ function A_mul_Bc{TA,TB}(A::AbstractArray{TA}, B::Union(QRCompactWYQ{TB},QRPacke
284284
convert(AbstractMatrix{TAB}, B))
285285
end
286286

287-
A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, b::StridedVector{T}) = (A_ldiv_B!(Triangular(A[:R], :U), sub(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b)
288-
A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, B::StridedMatrix{T}) = (A_ldiv_B!(Triangular(A[:R], :U), sub(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B)
287+
A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, b::StridedVector{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b)
288+
A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, B::StridedMatrix{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B)
289289

290290
# Julia implementation similarly to xgelsy
291291
function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real)
@@ -313,7 +313,7 @@ function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Re
313313
# if cond(r[1:rnk, 1:rnk])*rcond < 1 break end
314314
end
315315
C, τ = LAPACK.tzrzf!(A.factors[1:rnk,:])
316-
A_ldiv_B!(Triangular(C[1:rnk,1:rnk],:U),sub(Ac_mul_B!(getq(A),sub(B, 1:mA, 1:nrhs)),1:rnk,1:nrhs))
316+
A_ldiv_B!(UpperTriangular(C[1:rnk,1:rnk]),sub(Ac_mul_B!(getq(A),sub(B, 1:mA, 1:nrhs)),1:rnk,1:nrhs))
317317
B[rnk+1:end,:] = zero(T)
318318
LAPACK.ormrz!('L', iseltype(B, Complex) ? 'C' : 'T', C, τ, sub(B,1:nA,1:nrhs))
319319
B[1:nA,:] = sub(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:]

base/linalg/generic.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## linalg.jl: Some generic Linear Algebra definitions
22

3+
# Fall back arithmetic
4+
+(A::AbstractMatrix, B::AbstractMatrix) = full(A) + full(B)
5+
-(A::AbstractMatrix, B::AbstractMatrix) = full(A) - full(B)
6+
37
scale(X::AbstractArray, s::Number) = scale!(copy(X), s)
48
scale(s::Number, X::AbstractArray) = scale!(copy(X), s)
59

@@ -424,7 +428,7 @@ function elementaryRightTrapezoid!(A::AbstractMatrix, row::Integer)
424428
end
425429

426430
function det(A::AbstractMatrix)
427-
(istriu(A) || istril(A)) && return det(Triangular(A, :U, false))
431+
(istriu(A) || istril(A)) && return det(UpperTriangular(A))
428432
return det(lufact(A))
429433
end
430434
det(x::Number) = x

base/linalg/lu.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ function getindex{T,S<:StridedMatrix}(A::LU{T,S}, d::Symbol)
114114
end
115115

116116
A_ldiv_B!{T<:BlasFloat, S<:StridedMatrix}(A::LU{T, S}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info
117-
A_ldiv_B!{T,S<:StridedMatrix}(A::LU{T,S}, b::StridedVector) = A_ldiv_B!(Triangular(A.factors, :U, false), A_ldiv_B!(Triangular(A.factors, :L, true), b[ipiv2perm(A.ipiv, length(b))]))
118-
A_ldiv_B!{T,S<:StridedMatrix}(A::LU{T,S}, B::StridedMatrix) = A_ldiv_B!(Triangular(A.factors, :U, false), A_ldiv_B!(Triangular(A.factors, :L, true), B[ipiv2perm(A.ipiv, size(B, 1)),:]))
117+
A_ldiv_B!{T,S<:StridedMatrix}(A::LU{T,S}, b::StridedVector) = A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), b[ipiv2perm(A.ipiv, length(b))]))
118+
A_ldiv_B!{T,S<:StridedMatrix}(A::LU{T,S}, B::StridedMatrix) = A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B[ipiv2perm(A.ipiv, size(B, 1)),:]))
119119
At_ldiv_B{T<:BlasFloat,S<:StridedMatrix}(A::LU{T,S}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, copy(B)) A.info
120120
Ac_ldiv_B{T<:BlasComplex,S<:StridedMatrix}(A::LU{T,S}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, copy(B)) A.info
121121
At_ldiv_Bt{T<:BlasFloat,S<:StridedMatrix}(A::LU{T,S}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info

base/linalg/sparse.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ end
126126
*{TvA,TiA}(X::BitArray{2}, A::SparseMatrixCSC{TvA,TiA}) = invoke(*, (AbstractMatrix, SparseMatrixCSC), X, A)
127127
# TODO: Tridiagonal * Sparse should be implemented more efficiently
128128
*{TX,TvA,TiA}(X::Tridiagonal{TX}, A::SparseMatrixCSC{TvA,TiA}) = invoke(*, (Tridiagonal, AbstractMatrix), X, A)
129-
*{TvA,TiA}(X::Triangular, A::SparseMatrixCSC{TvA,TiA}) = full(X)*A
129+
*{TvA,TiA}(X::TriangularUnion, A::SparseMatrixCSC{TvA,TiA}) = full(X)*A
130130
function *{TX,TvA,TiA}(X::AbstractMatrix{TX}, A::SparseMatrixCSC{TvA,TiA})
131131
mX, nX = size(X)
132132
nX == A.m || throw(DimensionMismatch())

base/linalg/special.jl

+15-11
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
convert{T}(::Type{Bidiagonal}, A::Diagonal{T})=Bidiagonal(A.diag, zeros(T, size(A.diag,1)-1), true)
55
convert{T}(::Type{SymTridiagonal}, A::Diagonal{T})=SymTridiagonal(A.diag, zeros(T, size(A.diag,1)-1))
66
convert{T}(::Type{Tridiagonal}, A::Diagonal{T})=Tridiagonal(zeros(T, size(A.diag,1)-1), A.diag, zeros(T, size(A.diag,1)-1))
7-
convert(::Type{Triangular}, A::Diagonal) = Triangular(full(A), :L)
8-
convert(::Type{Triangular}, A::Bidiagonal) = Triangular(full(A), A.isupper ? :U : :L)
7+
convert(::Type{UpperTriangular}, A::Diagonal) = UpperTriangular(full(A), :L)
8+
convert(::Type{UnitUpperTriangular}, A::Diagonal) = UnitUpperTriangular(full(A), :L)
9+
convert(::Type{LowerTriangular}, A::Diagonal) = LowerTriangular(full(A), :L)
10+
convert(::Type{UnitLowerTriangular}, A::Diagonal) = UnitLowerTriangular(full(A), :L)
11+
convert(::Type{LowerTriangular}, A::Bidiagonal) = !A.isupper ? LowerTriangular(full(A)) : throw(ArgumentError("Bidiagonal matrix must have lower off diagonal to be converted to LowerTriangular"))
12+
convert(::Type{UpperTriangular}, A::Bidiagonal) = A.isupper ? UpperTriangular(full(A)) : throw(ArgumentError("Bidiagonal matrix must have upper off diagonal to be converted to UpperTriangular"))
913
convert(::Type{Matrix}, D::Diagonal) = diagm(D.diag)
1014

1115
function convert(::Type{Diagonal}, A::Union(Bidiagonal, SymTridiagonal))
@@ -42,12 +46,12 @@ function convert(::Type{SymTridiagonal}, A::Tridiagonal)
4246
SymTridiagonal(A.d, A.dl)
4347
end
4448

45-
function convert(::Type{Diagonal}, A::Triangular)
49+
function convert(::Type{Diagonal}, A::TriangularUnion)
4650
full(A) == diagm(diag(A)) || throw(ArgumentError("Matrix cannot be represented as Diagonal"))
4751
Diagonal(diag(A))
4852
end
4953

50-
function convert(::Type{Bidiagonal}, A::Triangular)
54+
function convert(::Type{Bidiagonal}, A::TriangularUnion)
5155
fA = full(A)
5256
if fA == diagm(diag(A)) + diagm(diag(fA, 1), 1)
5357
return Bidiagonal(diag(A), diag(fA,1), true)
@@ -58,9 +62,9 @@ function convert(::Type{Bidiagonal}, A::Triangular)
5862
end
5963
end
6064

61-
convert(::Type{SymTridiagonal}, A::Triangular) = convert(SymTridiagonal, convert(Tridiagonal, A))
65+
convert(::Type{SymTridiagonal}, A::TriangularUnion) = convert(SymTridiagonal, convert(Tridiagonal, A))
6266

63-
function convert(::Type{Tridiagonal}, A::Triangular)
67+
function convert(::Type{Tridiagonal}, A::TriangularUnion)
6468
fA = full(A)
6569
if fA == diagm(diag(A)) + diagm(diag(fA, 1), 1) + diagm(diag(fA, -1), -1)
6670
return Tridiagonal(diag(fA, -1), diag(A), diag(fA,1))
@@ -82,7 +86,7 @@ macro commutative(myexpr)
8286
end
8387

8488
for op in (:+, :-)
85-
SpecialMatrices = [:Diagonal, :Bidiagonal, :Tridiagonal, :Triangular, :Matrix]
89+
SpecialMatrices = [:Diagonal, :Bidiagonal, :Tridiagonal, :Matrix]
8690
for (idx, matrixtype1) in enumerate(SpecialMatrices) #matrixtype1 is the sparser matrix type
8791
for matrixtype2 in SpecialMatrices[idx+1:end] #matrixtype2 is the denser matrix type
8892
@eval begin #TODO quite a few of these conversions are NOT defined...
@@ -93,7 +97,7 @@ for op in (:+, :-)
9397
end
9498

9599
for matrixtype1 in (:SymTridiagonal,) #matrixtype1 is the sparser matrix type
96-
for matrixtype2 in (:Tridiagonal, :Triangular, :Matrix) #matrixtype2 is the denser matrix type
100+
for matrixtype2 in (:Tridiagonal, :Matrix) #matrixtype2 is the denser matrix type
97101
@eval begin
98102
($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B)
99103
($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B))
@@ -111,7 +115,7 @@ for op in (:+, :-)
111115
end
112116
end
113117

114-
A_mul_Bc!(A::Triangular, B::QRCompactWYQ) = A_mul_Bc!(full!(A),B)
115-
A_mul_Bc!(A::Triangular, B::QRPackedQ) = A_mul_Bc!(full!(A),B)
116-
A_mul_Bc(A::Triangular, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B)
118+
A_mul_Bc!(A::TriangularUnion, B::QRCompactWYQ) = A_mul_Bc!(full!(A),B)
119+
A_mul_Bc!(A::TriangularUnion, B::QRPackedQ) = A_mul_Bc!(full!(A),B)
120+
A_mul_Bc(A::TriangularUnion, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B)
117121

0 commit comments

Comments
 (0)