@@ -112,50 +112,95 @@ end
112
112
113
113
abstract Factorization{T}
114
114
115
- type Cholesky {T} <: Factorization{T}
115
+ type CholeskyDense {T} <: Factorization{T}
116
116
LR:: Matrix{T}
117
117
uplo:: LapackChar
118
- function Cholesky (A:: Matrix{T} , ul:: LapackChar )
119
- if ul != ' U' && ul != ' L' error (" Cholesky: uplo must be 'U' or 'L'" ) end
120
- Acopy = copy (A)
121
- _jl_lapack_potrf (ul, Acopy) == 0 ? new (ul == ' U' ? triu (Acopy) : tril (Acopy), ul) : error (" Cholesky: Matrix is not positive-definite" )
118
+ end
119
+
120
+ # chol() does not check that input matrix is symmetric/hermitian
121
+ # It simply uses upper triangular half
122
+ function chol {T<:LapackScalar} (A:: Matrix{T} , ul:: LapackChar )
123
+ if ul != ' U' && ul != ' L' ; error (" Cholesky: uplo must be 'U' or 'L'" ); end
124
+ C = CholeskyDense {T} (Array (T, size (A)), ul)
125
+ chol (C, A)
126
+ end
127
+ chol {T<:Real} (A:: Matrix{T} , ul:: LapackChar ) = chol (float64 (A), ul)
128
+ chol (A) = chol (A, ' U' )
129
+
130
+ function _chol {T<:LapackScalar} (C:: CholeskyDense{T} )
131
+ if _jl_lapack_potrf (C. uplo, C. LR) != 0
132
+ error (" Cholesky: Matrix is not positive-definite" )
122
133
end
134
+ if C. uplo == ' U'
135
+ triu! (C. LR)
136
+ else
137
+ tril! (C. LR)
138
+ end
139
+ C
140
+ end
141
+ function chol {T} (C:: CholeskyDense{T} , A:: Matrix{T} )
142
+ copy_to (C. LR, A)
143
+ _chol (C)
144
+ end
145
+ function chol! {T<:LapackScalar} (A:: Matrix{T} , ul:: LapackChar )
146
+ C = CholeskyDense {T} (A, ul)
147
+ _chol (C)
123
148
end
149
+
150
+ factors (C:: CholeskyDense ) = C. LR
124
151
125
- Cholesky (A:: Matrix ) = Cholesky {eltype(A)} (A, ' U' )
126
152
127
- (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(C:: Cholesky {T} , B:: StridedVecOrMat{T} ) =
153
+ (\ ){T<: LapackScalar }(C:: CholeskyDense {T} , B:: StridedVecOrMat{T} ) =
128
154
_jl_lapack_potrs (C. uplo, C. LR, copy (B))
129
155
130
- inv (C:: Cholesky ) = _jl_lapack_potri (C. uplo, copy (C. LR)) # should symmetrize the result
156
+ inv {T<:LapackScalar} (C:: CholeskyDense{T} ) = _jl_lapack_potri (C. uplo, copy (C. LR)) # should symmetrize the result
131
157
132
- type LU {T} <: Factorization{T}
158
+ type LUDense {T} <: Factorization{T}
133
159
lu:: Matrix{T}
134
160
ipiv:: Vector{Int32}
135
- function LU (lu:: Matrix{T} , ipiv:: Vector{Int32} )
161
+ function LUDense (lu:: Matrix{T} , ipiv:: Vector{Int32} )
136
162
m, n = size (lu)
137
- m == numel (ipiv) ? new (lu, ipiv) : error (" LU : dimension mismatch" )
163
+ m == numel (ipiv) ? new (lu, ipiv) : error (" LUDense : dimension mismatch" )
138
164
end
139
165
end
166
+ size (A:: LUDense ) = size (A. lu)
167
+ size (A:: LUDense ,n) = size (A. lu,n)
140
168
141
- function LU {T<:Union(Float64,Float32,Complex64,Complex128)} (A:: Matrix{T} )
142
- lu, ipiv = _jl_lapack_getrf (copy (A))
143
- LU {T} (lu, ipiv)
169
+ lu {T<:LapackScalar} (A:: Matrix{T} ) = lu! (copy (A))
170
+ function lu! {T<:LapackScalar} (A:: Matrix{T} )
171
+ lu, ipiv = _jl_lapack_getrf (A)
172
+ LUDense {T} (lu, ipiv)
144
173
end
145
174
146
- LU {T<:Number } (A:: Matrix{T} ) = LU (float64 (A))
175
+ lu {T<:Real } (A:: Matrix{T} ) = lu (float64 (A))
147
176
148
- function det (lu:: LU )
177
+ function det (lu:: LUDense )
149
178
m, n = size (lu. lu)
150
179
if m != n error (" det only defined for square matrices" ) end
151
180
prod (diag (lu. lu)) * (bool (sum (lu. ipiv .!= 1 : n) % 2 ) ? - 1 : 1 )
152
181
end
153
182
154
- det (A:: Matrix ) = det (LU (A))
183
+ det (A:: Matrix ) = det (lu (A))
155
184
156
- (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(lu:: LU {T} , B:: StridedVecOrMat{T} ) =
185
+ (\ ){T<: LapackScalar }(lu:: LUDense {T} , B:: StridedVecOrMat{T} ) =
157
186
_jl_lapack_getrs (' N' , lu. lu, lu. ipiv, copy (B))
158
- inv (lu:: LU ) = _jl_lapack_getri (copy (lu. lu), lu. ipiv)
187
+
188
+ inv {T<:LapackScalar} (lu:: LUDense{T} ) = _jl_lapack_getri (copy (lu. lu), lu. ipiv)
189
+
190
+ function factors {T<:LapackScalar} (lu:: LUDense{T} )
191
+ LU, ipiv = lu. lu, lu. ipiv
192
+ m, n = size (LU)
193
+
194
+ L = m >= n ? tril (LU, - 1 ) + eye (m,n) : tril (LU, - 1 )[:, 1 : m] + eye (m,m)
195
+ U = m <= n ? triu (LU) : triu (LU)[1 : n, :]
196
+ P = [1 : m]
197
+ for i= 1 : min (m,n)
198
+ t = P[i]
199
+ P[i] = P[ipiv[i]]
200
+ P[ipiv[i]] = t
201
+ end
202
+ L, U, P
203
+ end
159
204
160
205
# # Multiplication by Q or Q' from a QR factorization
161
206
for (orm2r, elty) in
@@ -193,82 +238,80 @@ for (orm2r, elty) in
193
238
end
194
239
end
195
240
196
- type QR{T} <: Factorization{T}
241
+ abstract QRFactorization{T} <: Factorization{T}
242
+
243
+ # # QR decomposition without column pivots
244
+ type QRDense{T} <: QRFactorization{T}
197
245
hh:: Matrix{T} # Householder transformations and R
198
246
tau:: Vector{T} # Scalar factors of transformations
199
- function QR (hh:: Matrix{T} , tt:: Vector{T} )
247
+ function QRDense (hh:: Matrix{T} , tt:: Vector{T} )
200
248
numel (tt) == min (size (hh)) ? new (hh, tt) : error (" QR: mismatched dimensions" )
201
249
end
202
250
end
251
+ size (A:: QRFactorization ) = size (A. hh)
252
+ size (A:: QRFactorization ,n) = size (A. hh,n)
203
253
204
- function QR (A:: Matrix )
254
+ function qr {T<:LapackScalar} (A:: StridedMatrix{T} )
205
255
hh, tt = _jl_lapack_geqrf (copy (A))
206
- QR {typeof(A[1] )} (hh, tt)
256
+ QRDense {eltype(A )} (hh, tt)
207
257
end
208
258
209
- size {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QR{T} ) = size (A. hh)
210
- size {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QR{T} ,n) = size (A. hh,n)
259
+ qr {T<:Real} (x:: StridedMatrix{T} ) = qr (float64 (x))
260
+
261
+ function factors {T<:LapackScalar} (qrd:: QRDense{T} )
262
+ aa, tau = qrd. hh, qrd. tau
263
+ R = triu (aa[1 : min (size (qrd)),:])
264
+ _jl_lapack_orgqr (aa, tau), R
265
+ end
211
266
212
267
# # Multiplication by Q from the QR decomposition
213
- function (* ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QR{T} ,
214
- B:: StridedVecOrMat{T} )
268
+ (* ){T<: LapackScalar }(A:: QRFactorization{T} , B:: StridedVecOrMat{T} ) =
215
269
_jl_lapack_orm2r (' L' , ' N' , A. hh, size (A, 2 ), A. tau, copy (B))
216
- end
217
270
218
271
# # Multiplication by Q' from the QR decomposition
219
- function Ac_mul_B {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QR{T} ,
220
- B:: StridedVecOrMat{T} )
272
+ Ac_mul_B {T<:LapackScalar} (A:: QRFactorization{T} , B:: StridedVecOrMat{T} ) =
221
273
_jl_lapack_orm2r (' L' , iscomplex (A. tau) ? ' C' : ' T' , A. hh, size (A, 2 ), A. tau, copy (B))
222
- end
223
274
224
275
# # Least squares solution. Should be more careful about cases with m < n
225
- function (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QR{T} ,
226
- B:: StridedVecOrMat{T} )
276
+ function (\ ){T<: LapackScalar }(A:: QRDense{T} , B:: StridedVecOrMat{T} )
227
277
n = numel (A. tau)
228
278
qtb = isa (B, Vector) ? (A' * B)[1 : n] : (A' * B)[1 : n, :]
229
279
# # Not sure if this avoids copying A.hh[1:n,:] but at least it is not all of A.hh
230
280
_jl_lapack_trtrs (' U' ,' N' ,' N' , A. hh[1 : n,:], qtb)
231
281
end
232
282
233
- type QRP {T} <: Factorization {T}
283
+ type QRPDense {T} <: QRFactorization {T}
234
284
hh:: Matrix{T}
235
285
tau:: Vector{T}
236
286
jpvt:: Vector{Int32}
237
- function QRP (hh:: Matrix{T} , tt:: Vector{T} , jj:: Vector{Int32} )
287
+ function QRPDense (hh:: Matrix{T} , tt:: Vector{T} , jj:: Vector{Int32} )
238
288
m, n = size (hh)
239
- numel (tt) == min (m,n) && numel (jj) == n ? new (hh,tt,jj) : error (" QRP : mismatched dimensions" )
289
+ numel (tt) == min (m,n) && numel (jj) == n ? new (hh,tt,jj) : error (" QRPDense : mismatched dimensions" )
240
290
end
241
291
end
242
292
243
- function QRP (A:: Matrix )
244
- hh, tt, jj = _jl_lapack_geqp3 (copy (A))
245
- QRP {typeof(A[1])} (hh, tt, jj)
246
- end
247
-
248
- # # Not sure how to avoid cut-and-paste programming on these.
249
- # # Create another abstract type with both QR{T} and QRP{T} as subtypes?
250
- size {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QRP{T} ) = size (A. hh)
251
- size {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QRP{T} ,n) = size (A. hh,n)
252
-
253
- function (* ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QRP{T} ,
254
- B:: StridedVecOrMat{T} )
255
- _jl_lapack_orm2r (' L' , ' N' , A. hh, size (A, 2 ), A. tau, copy (B))
293
+ function qrp {T<:LapackScalar} (A:: StridedMatrix{T} )
294
+ aa, tau, jpvt = _jl_lapack_geqp3 (copy (A))
295
+ QRPDense {T} (aa, tau, jpvt)
256
296
end
297
+ qrp {T<:Real} (x:: StridedMatrix{T} ) = qrp (float64 (x))
257
298
258
- function Ac_mul_B {T<:Union(Float64,Float32,Complex128,Complex64)} (A:: QRP{T} ,
259
- B:: StridedVecOrMat{T} )
260
- _jl_lapack_orm2r (' L' , iscomplex (A. tau) ? ' C' : ' T' , A. hh, size (A, 2 ), A. tau, copy (B))
299
+ function factors {T<:LapackScalar} (qrpd:: QRPDense{T} )
300
+ aa, tau = qrpd. hh, qrpd. tau
301
+ R = triu (aa[1 : min (size (qrpd)),:])
302
+ _jl_lapack_orgqr (aa, tau), R, qrpd. jpvt
261
303
end
262
304
263
- function (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QRP{T} ,
305
+ # FIXME \
306
+ function (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QRPDense{T} ,
264
307
B:: StridedVecOrMat{T} )
265
308
n = numel (A. tau)
266
309
# # Replace this with a direct call to _jl_lapack_trtrs to save copying A.hh?
267
310
# # Actually would need to call the appropriate Lapack subroutine to save copying.
268
311
triu (A. hh[1 : n,:]) \ (A' * B)[1 : n]
269
312
end
270
313
271
- function (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QRP {T} ,
314
+ function (\ ){T<: Union(Float64,Float32,Complex128,Complex64) }(A:: QRPDense {T} ,
272
315
B:: StridedVecOrMat{T} )
273
316
# # may be better to define one method for B::Vector{T} and another for StridedMatrix
274
317
BV = isa (B, Vector)
@@ -288,13 +331,12 @@ type LDLTTridiagonal{T} <: Factorization{T}
288
331
D:: Vector{T}
289
332
E:: Vector{T}
290
333
end
291
- function LDLTTridiagonal {T<:LapackScalar} (A:: Tridiagonal{T} )
334
+ function ldlt {T<:LapackScalar} (A:: Tridiagonal{T} )
292
335
D = copy (A. d)
293
336
E = copy (A. dl)
294
337
_jl_lapack_pttrf (D, E)
295
- LDLTTridiagonal (D, E)
338
+ LDLTTridiagonal {T} (D, E)
296
339
end
297
- LDLT (A:: Tridiagonal ) = LDLTTridiagonal (A)
298
340
299
341
(\ ){T<: LapackScalar }(C:: LDLTTridiagonal{T} , B:: StridedVecOrMat{T} ) =
300
342
_jl_lapack_pttrs (C. D, C. E, copy (B))
@@ -304,25 +346,21 @@ type LUTridiagonal{T} <: Factorization{T}
304
346
ipiv:: Vector{Int32}
305
347
function LUTridiagonal (lu:: Tridiagonal{T} , ipiv:: Vector{Int32} )
306
348
m, n = size (lu)
307
- m == numel (ipiv) ? new (lu, ipiv) : error (" LU : dimension mismatch" )
349
+ m == numel (ipiv) ? new (lu, ipiv) : error (" LUTridiagonal : dimension mismatch" )
308
350
end
309
351
end
310
352
show (io, lu:: LUTridiagonal ) = print (io, " LU decomposition of " , summary (lu. lu))
311
353
312
- function LU {T<:LapackScalar} (A:: Tridiagonal{T} )
354
+ function lu {T<:LapackScalar} (A:: Tridiagonal{T} )
313
355
lu, ipiv = _jl_lapack_gttrf (copy (A))
314
356
LUTridiagonal {T} (lu, ipiv)
315
357
end
316
358
317
- function lu (A:: Tridiagonal )
318
- error (" lu(A) is not defined when A is Tridiagonal. Use LU(A) instead." )
319
- end
320
-
321
359
function det (lu:: LUTridiagonal )
322
360
prod (lu. lu. d) * (bool (sum (lu. ipiv .!= 1 : n) % 2 ) ? - 1 : 1 )
323
361
end
324
362
325
- det (A:: Tridiagonal ) = det (LU (A))
363
+ det (A:: Tridiagonal ) = det (lu (A))
326
364
327
365
(\ ){T<: LapackScalar }(lu:: LUTridiagonal{T} , B:: StridedVecOrMat{T} ) =
328
366
_jl_lapack_gttrs (' N' , lu. lu, lu. ipiv, copy (B))
0 commit comments