Skip to content

Commit 119ebc2

Browse files
committed
Merge pull request #5330 from JuliaLang/anj/pivots
Deprecate cholpfact and qrpfact and introduce keyword arguments for pivoting. Make thin a keyword argument.
2 parents ef4641c + b6c4126 commit 119ebc2

File tree

9 files changed

+113
-143
lines changed

9 files changed

+113
-143
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ Deprecated or removed
105105
argument specifying the floating point type to which they apply. The old
106106
behaviour and `[get/set/with]_bigfloat_rounding` functions are deprecated ([#5007])
107107

108+
* cholpfact and qrpfact are deprecated in favor of keyword arguments in
109+
cholfact and qrfact.
110+
108111
[#4042]: https://github.com/JuliaLang/julia/issues/4042
109112
[#5164]: https://github.com/JuliaLang/julia/issues/5164
110113
[#5214]: https://github.com/JuliaLang/julia/issues/5214
@@ -135,6 +138,7 @@ Deprecated or removed
135138
[#5277]: https://github.com/JuliaLang/julia/issues/5277
136139
[#987]: https://github.com/JuliaLang/julia/issues/987
137140
[#2345]: https://github.com/JuliaLang/julia/issues/2345
141+
[#5330]: https://github.com/JuliaLang/julia/issues/5330
138142

139143
Julia v0.2.0 Release Notes
140144
==========================

base/deprecated.jl

+8
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ export PipeString
168168
# copy!(dest::AbstractArray, doffs::Integer, src::Integer)
169169
# in abstractarray.jl
170170
@deprecate copy!(dest::AbstractArray, src, doffs::Integer) copy!(dest, doffs, src)
171+
@deprecate qrpfact!(A) qrfact!(A, pivot=true)
172+
@deprecate qrpfact(A) qrfact(A, pivot=true)
173+
@deprecate qrp(A, thin) qr(A, thin=thin, pivot=true)
174+
@deprecate qrp(A) qr(A, pivot=true)
175+
@deprecate cholpfact!(A) cholfact!(A, :U, pivot=true)
176+
@deprecate cholpfact!(A,tol=tol) cholfact!(A, :U, pivot=true, tol=tol)
177+
@deprecate cholpfact!(A,uplo,tol=tol) cholfact!(A, uplo, pivot=true, tol=tol)
178+
@deprecate cholpfact(A) cholfact(A, :U, pivot=true)
171179

172180
deprecated_ls() = run(`ls -l`)
173181
deprecated_ls(args::Cmd) = run(`ls -l $args`)

base/linalg.jl

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export
111111
svdvals!,
112112
svdvals,
113113
symmetrize!,
114+
symmetrize_conj!,
114115
trace,
115116
transpose,
116117
tril,

base/linalg/dense.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ function factorize!{T}(A::Matrix{T})
423423
end
424424
return lufact!(A)
425425
end
426-
return qrpfact!(A)
426+
return qrfact!(A,pivot=true)
427427
end
428428

429429
factorize(A::AbstractMatrix) = factorize!(copy(A))
@@ -443,7 +443,7 @@ function (\){T<:BlasFloat}(A::StridedMatrix{T}, B::StridedVecOrMat{T})
443443
istriu(A) && return \(Triangular(A, :U),B)
444444
return \(lufact(A),B)
445445
end
446-
return qrpfact(A)\B
446+
return qrfact(A,pivot=true)\B
447447
end
448448

449449
## Moore-Penrose inverse

base/linalg/factorization.jl

+75-92
Original file line numberDiff line numberDiff line change
@@ -17,83 +17,51 @@ A_ldiv_B!(F::Factorization, B::StridedVecOrMat) = A_ldiv_B!(F, float(B))
1717
Ac_ldiv_B!(F::Factorization, B::StridedVecOrMat) = Ac_ldiv_B!(F, float(B))
1818
At_ldiv_B!(F::Factorization, B::StridedVecOrMat) = At_ldiv_B!(F, float(B))
1919

20+
##########################
21+
# Cholesky Factorization #
22+
##########################
2023
type Cholesky{T<:BlasFloat} <: Factorization{T}
2124
UL::Matrix{T}
2225
uplo::Char
2326
end
27+
type CholeskyPivoted{T<:BlasFloat} <: Factorization{T}
28+
UL::Matrix{T}
29+
uplo::Char
30+
piv::Vector{BlasInt}
31+
rank::BlasInt
32+
tol::Real
33+
info::BlasInt
34+
end
2435

25-
function cholfact!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol)
36+
function cholfact!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol=:U; pivot=false, tol=-1.0)
2637
uplochar = string(uplo)[1]
27-
C, info = LAPACK.potrf!(uplochar, A)
28-
@assertposdef Cholesky(C, uplochar) info
38+
if pivot
39+
A, piv, rank, info = LAPACK.pstrf!(uplochar, A, tol)
40+
return CholeskyPivoted{T}(A, uplochar, piv, rank, tol, info)
41+
else
42+
C, info = LAPACK.potrf!(uplochar, A)
43+
return @assertposdef Cholesky(C, uplochar) info
44+
end
2945
end
3046
cholfact!(A::StridedMatrix, args...) = cholfact!(float(A), args...)
31-
cholfact!{T<:BlasFloat}(A::StridedMatrix{T}) = cholfact!(A, :U)
32-
cholfact{T<:BlasFloat}(A::StridedMatrix{T}, args...) = cholfact!(copy(A), args...)
33-
cholfact(A::StridedMatrix, args...) = cholfact!(float(A), args...)
47+
cholfact{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol=:U; pivot=false, tol=-1.0) = cholfact!(copy(A), uplo, pivot=pivot, tol=tol)
48+
cholfact(A::StridedMatrix, uplo::Symbol=:U; pivot=false, tol=-1.0) = cholfact!(float(A), uplo, pivot=pivot, tol=tol)
3449
cholfact(x::Number) = @assertposdef Cholesky(fill(sqrt(x), 1, 1), :U) !(imag(x) == 0 && real(x) > 0)
3550

36-
chol(A::Union(Number, AbstractMatrix), uplo::Symbol) = cholfact(A, uplo)[uplo]
37-
chol(A::Union(Number, AbstractMatrix)) = cholfact(A, :U)[:U]
51+
chol(A::Union(Number, AbstractMatrix), uplo::Symbol=:U) = cholfact(A, uplo)[uplo]
3852

3953
size(C::Cholesky) = size(C.UL)
4054
size(C::Cholesky,d::Integer) = size(C.UL,d)
4155

4256
function getindex(C::Cholesky, d::Symbol)
43-
C.uplo == 'U' ? triu!(C.UL) : tril!(C.UL)
44-
if d == :U || d == :L
45-
return symbol(C.uplo) == d ? C.UL : C.UL'
46-
elseif d == :UL
47-
return Triangular(C.UL, C.uplo)
48-
end
57+
d == :U && return triu!(symbol(C.uplo) == d ? C.UL : C.UL')
58+
d == :L && return tril!(symbol(C.uplo) == d ? C.UL : C.UL')
59+
d == :UL && return Triangular(C.UL, C.uplo)
4960
throw(KeyError(d))
5061
end
51-
52-
A_ldiv_B!{T<:BlasFloat}(C::Cholesky{T}, B::StridedVecOrMat{T}) = LAPACK.potrs!(C.uplo, C.UL, B)
53-
54-
function det{T}(C::Cholesky{T})
55-
dd = one(T)
56-
for i in 1:size(C.UL,1) dd *= abs2(C.UL[i,i]) end
57-
dd
58-
end
59-
60-
function logdet{T}(C::Cholesky{T})
61-
dd = zero(T)
62-
for i in 1:size(C.UL,1) dd += log(C.UL[i,i]) end
63-
dd + dd # instead of 2.0dd which can change the type
64-
end
65-
66-
inv(C::Cholesky)=symmetrize_conj!(LAPACK.potri!(C.uplo, copy(C.UL)), C.uplo)
67-
68-
## Pivoted Cholesky
69-
type CholeskyPivoted{T<:BlasFloat} <: Factorization{T}
70-
UL::Matrix{T}
71-
uplo::Char
72-
piv::Vector{BlasInt}
73-
rank::BlasInt
74-
tol::Real
75-
info::BlasInt
76-
end
77-
function CholeskyPivoted{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Char, tol::Real)
78-
A, piv, rank, info = LAPACK.pstrf!(uplo, A, tol)
79-
CholeskyPivoted{T}((uplo == 'U' ? triu! : tril!)(A), uplo, piv, rank, tol, info)
80-
end
81-
82-
chkfullrank(C::CholeskyPivoted) = C.rank<size(C.UL, 1) && throw(RankDeficientException(C.info))
83-
84-
cholpfact!(A::StridedMatrix, args...) = cholpfact!(float(A), args...)
85-
cholpfact!{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Symbol, tol::Real) = CholeskyPivoted(A, string(uplo)[1], tol)
86-
cholpfact!{T<:BlasFloat}(A::StridedMatrix{T}, tol::Real) = cholpfact!(A, :U, tol)
87-
cholpfact!{T<:BlasFloat}(A::StridedMatrix{T}) = cholpfact!(A, -1.)
88-
cholpfact{T<:BlasFloat}(A::StridedMatrix{T}, args...) = cholpfact!(copy(A), args...)
89-
cholpfact(A::StridedMatrix, args...) = cholpfact!(float(A), args...)
90-
91-
size(C::CholeskyPivoted) = size(C.UL)
92-
size(C::CholeskyPivoted,d::Integer) = size(C.UL,d)
93-
94-
getindex(C::CholeskyPivoted) = C.UL, C.piv
9562
function getindex{T<:BlasFloat}(C::CholeskyPivoted{T}, d::Symbol)
96-
(d == :U || d == :L) && return symbol(C.uplo) == d ? C.UL : C.UL'
63+
d == :U && return triu!(symbol(C.uplo) == d ? C.UL : C.UL')
64+
d == :L && return tril!(symbol(C.uplo) == d ? C.UL : C.UL')
9765
d == :p && return C.piv
9866
if d == :P
9967
n = size(C, 1)
@@ -106,6 +74,10 @@ function getindex{T<:BlasFloat}(C::CholeskyPivoted{T}, d::Symbol)
10674
throw(KeyError(d))
10775
end
10876

77+
show(io::IO, C::Cholesky) = (println("$(typeof(C)) with factor:");show(io,C[symbol(C.uplo)]))
78+
79+
A_ldiv_B!{T<:BlasFloat}(C::Cholesky{T}, B::StridedVecOrMat{T}) = LAPACK.potrs!(C.uplo, C.UL, B)
80+
10981
function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedVector{T})
11082
chkfullrank(C)
11183
ipermute!(LAPACK.potrs!(C.uplo, C.UL, permute!(B, C.piv)), C.piv)
@@ -124,17 +96,35 @@ function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedMatrix{T})
12496
B
12597
end
12698

127-
rank(C::CholeskyPivoted) = C.rank
99+
function det{T}(C::Cholesky{T})
100+
dd = one(T)
101+
for i in 1:size(C.UL,1) dd *= abs2(C.UL[i,i]) end
102+
dd
103+
end
128104

129105
det{T}(C::CholeskyPivoted{T}) = C.rank<size(C.UL,1) ? real(zero(T)) : prod(abs2(diag(C.UL)))
130106

107+
function logdet{T}(C::Cholesky{T})
108+
dd = zero(T)
109+
for i in 1:size(C.UL,1) dd += log(C.UL[i,i]) end
110+
dd + dd # instead of 2.0dd which can change the type
111+
end
112+
113+
inv(C::Cholesky)=symmetrize_conj!(LAPACK.potri!(C.uplo, copy(C.UL)), C.uplo)
114+
131115
function inv(C::CholeskyPivoted)
132116
chkfullrank(C)
133117
ipiv = invperm(C.piv)
134118
(symmetrize!(LAPACK.potri!(C.uplo, copy(C.UL)), C.uplo))[ipiv, ipiv]
135119
end
136120

137-
## LU
121+
chkfullrank(C::CholeskyPivoted) = C.rank<size(C.UL, 1) && throw(RankDeficientException(C.info))
122+
123+
rank(C::CholeskyPivoted) = C.rank
124+
125+
####################
126+
# LU Factorization #
127+
####################
138128
type LU{T<:BlasFloat} <: Factorization{T}
139129
factors::Matrix{T}
140130
ipiv::Vector{BlasInt}
@@ -204,7 +194,6 @@ function logdet{T<:Complex}(A::LU{T})
204194
complex(r,a)
205195
end
206196

207-
208197
A_ldiv_B!{T<:BlasFloat}(A::LU{T}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info
209198
At_ldiv_B{T<:BlasFloat}(A::LU{T}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, copy(B)) A.info
210199
Ac_ldiv_B{T<:BlasComplex}(A::LU{T}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, copy(B)) A.info
@@ -217,23 +206,33 @@ inv(A::LU)=@assertnonsingular LAPACK.getri!(copy(A.factors), A.ipiv) A.info
217206

218207
cond(A::LU, p) = inv(LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, norm(A[:L][A[:p],:]*A[:U], p)))
219208

220-
## QR decomposition without column pivots. By the faster geqrt3
209+
####################
210+
# QR Factorization #
211+
####################
212+
213+
# Note. For QR factorization without pivoting, the WY representation based method introduced in LAPACK 3.4
221214
type QR{S<:BlasFloat} <: Factorization{S}
222-
vs::Matrix{S} # the elements on and above the diagonal contain the N-by-N upper triangular matrix R; the elements below the diagonal are the columns of V
223-
T::Matrix{S} # upper triangular factor of the block reflector.
215+
vs::Matrix{S}
216+
T::Matrix{S}
224217
end
225218
QR{T<:BlasFloat}(A::StridedMatrix{T}, nb::Integer = min(minimum(size(A)), 36)) = QR(LAPACK.geqrt!(A, nb)...)
226219

227-
qrfact!{T<:BlasFloat}(A::StridedMatrix{T}, args::Integer...) = QR(A, args...)
228-
qrfact!(A::StridedMatrix, args::Integer...) = qrfact!(float(A), args...)
229-
qrfact{T<:BlasFloat}(A::StridedMatrix{T}, args::Integer...) = qrfact!(copy(A), args...)
230-
qrfact(A::StridedMatrix, args::Integer...) = qrfact!(float(A), args...)
220+
type QRPivoted{T} <: Factorization{T}
221+
hh::Matrix{T}
222+
tau::Vector{T}
223+
jpvt::Vector{BlasInt}
224+
end
225+
226+
qrfact!{T<:BlasFloat}(A::StridedMatrix{T}; pivot=false) = pivot ? QRPivoted{T}(LAPACK.geqp3!(A)...) : QR(A)
227+
qrfact!(A::StridedMatrix; pivot=false) = qrfact!(float(A), pivot=pivot)
228+
qrfact{T<:BlasFloat}(A::StridedMatrix{T}; pivot=false) = qrfact!(copy(A), pivot=pivot)
229+
qrfact(A::StridedMatrix; pivot=false) = qrfact!(float(A), pivot=pivot)
231230
qrfact(x::Integer) = qrfact(float(x))
232231
qrfact(x::Number) = QR(fill(one(x), 1, 1), fill(x, 1, 1))
233232

234-
function qr(A::Union(Number, AbstractMatrix), thin::Bool=true)
235-
F = qrfact(A)
236-
full(F[:Q], thin), F[:R]
233+
function qr(A::Union(Number, AbstractMatrix); pivot=false, thin::Bool=true)
234+
F = qrfact(A, pivot=pivot)
235+
full(F[:Q], thin=thin), F[:R]
237236
end
238237

239238
size(A::QR, args::Integer...) = size(A.vs, args...)
@@ -253,9 +252,9 @@ QRPackedQ(A::QR) = QRPackedQ(A.vs, A.T)
253252
size(A::QRPackedQ, dim::Integer) = 0 < dim ? (dim <= 2 ? size(A.vs, 1) : 1) : throw(BoundsError())
254253
size(A::QRPackedQ) = size(A, 1), size(A, 2)
255254

256-
full{T<:BlasFloat}(A::QRPackedQ{T}, thin::Bool=true) = A * (thin ? eye(T, size(A.vs)...) : eye(T, size(A.vs,1)))
255+
full{T<:BlasFloat}(A::QRPackedQ{T}; thin::Bool=true) = A * (thin ? eye(T, size(A.vs)...) : eye(T, size(A.vs,1)))
257256

258-
print_matrix(io::IO, A::QRPackedQ, rows::Integer, cols::Integer) = print_matrix(io, full(A, false), rows, cols)
257+
print_matrix(io::IO, A::QRPackedQ, rows::Integer, cols::Integer) = print_matrix(io, full(A, thin=false), rows, cols)
259258

260259
## Multiplication by Q from the QR decomposition
261260
function *{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T})
@@ -274,22 +273,6 @@ end
274273
\(A::QR, B::StridedVector) = Triangular(A[:R], :U)\(A[:Q]'B)[1:size(A, 2)]
275274
\(A::QR, B::StridedMatrix) = Triangular(A[:R], :U)\(A[:Q]'B)[1:size(A, 2),:]
276275

277-
type QRPivoted{T} <: Factorization{T}
278-
hh::Matrix{T}
279-
tau::Vector{T}
280-
jpvt::Vector{BlasInt}
281-
end
282-
283-
qrpfact!{T<:BlasFloat}(A::StridedMatrix{T}) = QRPivoted{T}(LAPACK.geqp3!(A)...)
284-
qrpfact!(A::StridedMatrix) = qrpfact!(float(A))
285-
qrpfact{T<:BlasFloat}(A::StridedMatrix{T}) = qrpfact!(copy(A))
286-
qrpfact(A::StridedMatrix) = qrpfact!(float(A))
287-
288-
function qrp(A::AbstractMatrix, thin::Bool=false)
289-
F = qrpfact(A)
290-
full(F[:Q], thin), F[:R], F[:p]
291-
end
292-
293276
size(A::QRPivoted, args::Integer...) = size(A.hh, args...)
294277

295278
function getindex{T<:BlasFloat}(A::QRPivoted{T}, d::Symbol)
@@ -345,13 +328,13 @@ QRPivotedQ(A::QRPivoted) = QRPivotedQ(A.hh, A.tau)
345328

346329
size(A::QRPivotedQ, dims::Integer) = dims > 0 ? (dims < 3 ? size(A.hh, 1) : 1) : throw(BoundsError())
347330

348-
function full{T<:BlasFloat}(A::QRPivotedQ{T}, thin::Bool=true)
331+
function full{T<:BlasFloat}(A::QRPivotedQ{T}; thin::Bool=true)
349332
m, n = size(A.hh)
350333
Ahhpad = thin ? copy(A.hh) : [A.hh zeros(T, m, max(0, m - n))]
351334
LAPACK.orgqr!(Ahhpad, A.tau)
352335
end
353336

354-
print_matrix(io::IO, A::QRPivotedQ, rows::Integer, cols::Integer) = print_matrix(io, full(A, false), rows, cols)
337+
print_matrix(io::IO, A::QRPivotedQ, rows::Integer, cols::Integer) = print_matrix(io, full(A, thin=false), rows, cols)
355338

356339
## Multiplication by Q from the Pivoted QR decomposition
357340
function *{T<:BlasFloat}(A::QRPivotedQ{T}, B::StridedVecOrMat{T})

base/linalg/lapack.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,7 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in
16741674
(Ptr{BlasChar}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt},
16751675
Ptr{BlasInt}, Ptr{$rtyp}, Ptr{$rtyp}, Ptr{BlasInt}),
16761676
&uplo, &n, A, &max(1,stride(A,2)), piv, rank, &tol, work, info)
1677-
@lapackerror
1677+
@assertargsok
16781678
A, piv, rank[1], info[1] #Stored in PivotedCholesky
16791679
end
16801680
end

base/linalg/triangular.jl

+2-4
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,9 @@ end
8282

8383
size(A::Triangular, args...) = size(A.UL, args...)
8484
convert(::Type{Matrix}, A::Triangular) = full(A)
85-
full(A::Triangular) = A.UL
85+
full(A::Triangular) = A.uplo == 'U' ? triu!(A.UL) : tril!(A.UL)
8686

87-
getindex{T}(A::Triangular{T}, i::Integer, j::Integer) = i == j ? A.UL[i,j] : ((A.uplo == 'U') == (i < j) ? getindex(A.UL, i, j) : zero(T))
88-
89-
print_matrix(io::IO, A::Triangular, rows::Integer, cols::Integer) = print_matrix(io, full(A), rows, cols)
87+
getindex{T}(A::Triangular{T}, i::Integer, j::Integer) = i == j ? (A.unitdiag == 'U' ? one(T) : A.UL[i,j]) : ((A.uplo == 'U') == (i < j) ? getindex(A.UL, i, j) : zero(T))
9088

9189
istril(A::Triangular) = A.uplo == 'L' || istriu(A.UL)
9290
istriu(A::Triangular) = A.uplo == 'U' || istril(A.UL)

0 commit comments

Comments
 (0)