@@ -131,19 +131,42 @@ function lufact!{T}(A::AbstractMatrix{T})
131
131
m, n = size (A)
132
132
minmn = min (m,n)
133
133
info = 0
134
- for k = 1 : minmn- 1
135
- if A[k,k] == 0 ; info = k; break ; end
136
- for i = k+ 1 : m
137
- A[i,k] /= A[k,k]
134
+ ipiv = Array (BlasInt, minmn)
135
+ for k = 1 : minmn
136
+ # find index max
137
+ kp = 1
138
+ amax = zero (T)
139
+ for i = k: m
140
+ absi = abs (A[i,k])
141
+ if absi > amax
142
+ kp = i
143
+ amax = absi
144
+ end
145
+ end
146
+ ipiv[k] = kp
147
+ if A[kp,k] != 0
148
+ # Interchange
149
+ for i = 1 : n
150
+ tmp = A[k,i]
151
+ A[k,i] = A[kp,i]
152
+ A[kp,i] = tmp
153
+ end
154
+ # Scale first column
155
+ for i = k+ 1 : m
156
+ A[i,k] /= A[k,k]
157
+ end
158
+ elseif info == 0
159
+ info = k
138
160
end
161
+ # Update the rest
139
162
for j = k+ 1 : n
140
163
for i = k+ 1 : m
141
164
A[i,j] -= A[i,k]* A[k,j]
142
165
end
143
166
end
144
167
end
145
168
if minmn > 0 && A[minmn,minmn] == 0 ; info = minmn; end
146
- LU (A, BlasInt[ 1 : minmn] , convert (BlasInt, info))
169
+ LU (A, ipiv , convert (BlasInt, info))
147
170
end
148
171
lufact (A:: StridedMatrix ) = lufact! (copy (A))
149
172
lufact (x:: Number ) = LU (fill (x, 1 , 1 ), BlasInt[1 ], x == 0 ? one (BlasInt) : zero (BlasInt))
@@ -158,17 +181,20 @@ convert{T}(::Type{LU{T}}, F::LU) = LU(convert(Matrix{T}, F.factors), F.ipiv, F.i
158
181
size (A:: LU ) = size (A. factors)
159
182
size (A:: LU ,n) = size (A. factors,n)
160
183
184
+ function ipiv2perm {T} (v:: AbstractVector{T} , maxi:: Integer )
185
+ p = T[1 : maxi]
186
+ @inbounds for i in 1 : length (v)
187
+ p[i], p[v[i]] = p[v[i]], p[i]
188
+ end
189
+ return p
190
+ end
191
+
161
192
function getindex {T} (A:: LU{T} , d:: Symbol )
162
193
m, n = size (A)
163
194
d == :L && return tril (A. factors[1 : m, 1 : min (m,n)], - 1 ) + eye (T, m, min (m,n))
164
195
d == :U && return triu (A. factors[1 : min (m,n),1 : n])
165
- if d == :p
166
- p = [1 : m]
167
- for i in 1 : length (A. ipiv)
168
- p[i], p[A. ipiv[i]] = p[A. ipiv[i]], p[i]
169
- end
170
- return p
171
- elseif d == :P
196
+ d == :p && return ipiv2perm (A. ipiv, m)
197
+ if d == :P
172
198
p = A[:p ]
173
199
P = zeros (T, m, m)
174
200
for i in 1 : m
@@ -207,7 +233,8 @@ function logdet{T<:Complex}(A::LU{T})
207
233
end
208
234
209
235
A_ldiv_B! {T<:BlasFloat} (A:: LU{T} , B:: StridedVecOrMat{T} ) = @assertnonsingular LAPACK. getrs! (' N' , A. factors, A. ipiv, B) A. info
210
- A_ldiv_B! (A:: LU , B:: StridedVecOrMat ) = A_ldiv_B! (Triangular (A. factors, :U , false ), A_ldiv_B! (Triangular (A. factors, :L , true ), B))
236
+ A_ldiv_B! (A:: LU , b:: StridedVector ) = A_ldiv_B! (Triangular (A. factors, :U , false ), A_ldiv_B! (Triangular (A. factors, :L , true ), b[ipiv2perm (A. ipiv, length (b))]))
237
+ A_ldiv_B! (A:: LU , 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 )),:]))
211
238
At_ldiv_B {T<:BlasFloat} (A:: LU{T} , B:: StridedVecOrMat{T} ) = @assertnonsingular LAPACK. getrs! (' T' , A. factors, A. ipiv, copy (B)) A. info
212
239
Ac_ldiv_B {T<:BlasComplex} (A:: LU{T} , B:: StridedVecOrMat{T} ) = @assertnonsingular LAPACK. getrs! (' C' , A. factors, A. ipiv, copy (B)) A. info
213
240
At_ldiv_Bt {T<:BlasFloat} (A:: LU{T} , B:: StridedVecOrMat{T} ) = @assertnonsingular LAPACK. getrs! (' T' , A. factors, A. ipiv, transpose (B)) A. info
0 commit comments