@@ -86,65 +86,48 @@ for f! in (:lq_full!, :lq_compact!)
8686 end
8787end
8888
89- # Implementation
90- # --------------
91- function lq_full! (A:: AbstractMatrix , LQ, alg:: LAPACK_HouseholderLQ )
92- check_input (lq_full!, A, LQ, alg)
93- L, Q = LQ
94- _lapack_lq! (A, L, Q; alg. kwargs... )
95- return L, Q
96- end
97- function lq_compact! (A:: AbstractMatrix , LQ, alg:: LAPACK_HouseholderLQ )
98- check_input (lq_compact!, A, LQ, alg)
99- L, Q = LQ
100- _lapack_lq! (A, L, Q; alg. kwargs... )
101- return L, Q
102- end
103- function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LAPACK_HouseholderLQ )
104- check_input (lq_null!, A, Nᴴ, alg)
105- _lapack_lq_null! (A, Nᴴ; alg. kwargs... )
106- return Nᴴ
107- end
89+ # ==========================
90+ # IMPLEMENTATIONS
91+ # ==========================
10892
109- function lq_full! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
93+ # Householder
94+ # -----------
95+ function lq_full! (A, LQ, alg:: Householder )
11096 check_input (lq_full!, A, LQ, alg)
111- L, Q = LQ
112- lq_via_qr! (A, L, Q, alg. qr_alg)
113- return L, Q
97+ return householder_lq! (alg. driver, A, LQ... ; alg. kwargs... )
11498end
115- function lq_compact! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
99+ function lq_compact! (A, LQ, alg:: Householder )
116100 check_input (lq_compact!, A, LQ, alg)
117- L, Q = LQ
118- lq_via_qr! (A, L, Q, alg. qr_alg)
119- return L, Q
101+ return householder_lq! (alg. driver, A, LQ... ; alg. kwargs... )
120102end
121- function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LQViaTransposedQR )
103+ function lq_null! (A, Nᴴ, alg:: Householder )
122104 check_input (lq_null!, A, Nᴴ, alg)
123- lq_null_via_qr! (A, Nᴴ, alg. qr_alg)
124- return Nᴴ
105+ return householder_lq_null! (alg. driver, A, Nᴴ; alg. kwargs... )
125106end
126107
127- function lq_full! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
128- check_input (lq_full!, A, LQ, alg)
129- L, Q = LQ
130- _diagonal_lq! (A, L, Q; alg. kwargs... )
131- return L, Q
108+ householder_lq! (:: DefaultDriver , A, L, Q; kwargs... ) =
109+ householder_lq! (default_householder_driver (A), A, L, Q; kwargs... )
110+ householder_lq_null! (:: DefaultDriver , A, Nᴴ; kwargs... ) =
111+ householder_lq_null! (default_householder_driver (A), A, Nᴴ; kwargs... )
112+
113+ # dispatch helpers
114+ for f in (:gelqt! , :gemlqt! , :gelqf! , :unglq! , :unmlq! )
115+ @eval begin
116+ $ f (:: LAPACK , args... ) = YALAPACK.$ f (args... )
117+ end
132118end
133- function lq_compact! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
134- check_input (lq_compact!, A, LQ, alg)
135- L, Q = LQ
136- _diagonal_lq! (A, L, Q; alg. kwargs... )
137- return L, Q
119+
120+ function householder_lq! (driver:: Union{CUSOLVER, ROCSOLVER, GLA} , A, L, Q; kwargs... )
121+ qr_alg = driver === GLA () ? GLA_HouseholderQR (; kwargs... ) : Householder (driver; kwargs... )
122+ return lq_via_qr! (A, L, Q, qr_alg)
138123end
139- function lq_null! (A :: AbstractMatrix , N, alg :: DiagonalAlgorithm )
140- check_input (lq_null!, A, N, alg )
141- return _diagonal_lq_null ! (A, N; alg . kwargs ... )
124+ function householder_lq_null! (driver :: Union{CUSOLVER, ROCSOLVER, GLA} , A, Nᴴ; kwargs ... )
125+ qr_alg = driver === GLA () ? GLA_HouseholderQR (; kwargs ... ) : Householder (driver; kwargs ... )
126+ return lq_null_via_qr ! (A, Nᴴ, qr_alg )
142127end
143128
144- # LAPACK logic
145- # ------------
146- function _lapack_lq! (
147- A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
129+ function householder_lq! (
130+ driver:: LAPACK , A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
148131 positive = true , pivoted = false ,
149132 blocksize = ((pivoted || A === Q) ? 1 : YALAPACK. default_qr_blocksize (A))
150133 )
@@ -153,31 +136,29 @@ function _lapack_lq!(
153136 computeL = length (L) > 0
154137 inplaceQ = Q === A
155138
156- if pivoted && (blocksize > 1 )
157- throw (ArgumentError (" LAPACK does not provide a blocked implementation for a pivoted LQ decomposition" ))
158- end
159- if inplaceQ && (computeL || positive || blocksize > 1 || n < m)
160- throw (ArgumentError (" inplace Q only supported if matrix is wide (`m <= n`), L is not required, and using the unblocked algorithm (`blocksize=1`) with `positive=false`" ))
161- end
139+ pivoted && (blocksize > 1 ) &&
140+ throw (ArgumentError (lazy " $driver does not provide a blocked pivoted LQ decomposition" ))
141+ (inplaceQ && (computeL || positive || blocksize > 1 || n < m)) &&
142+ throw (ArgumentError (" inplace Q only supported if matrix is wide (`m <= n`), L is not required, and using the unblocked algorithm (`blocksize = 1`) with `positive = false`" ))
162143
163144 if blocksize > 1
164145 mb = min (minmn, blocksize)
165146 if computeL # first use L as space for T
166- A, T = YALAPACK . gelqt! (A, view (L, 1 : mb, 1 : minmn))
147+ A, T = gelqt! (driver, A, view (L, 1 : mb, 1 : minmn))
167148 else
168- A, T = YALAPACK . gelqt! (A, similar (A, mb, minmn))
149+ A, T = gelqt! (driver, A, similar (A, mb, minmn))
169150 end
170- Q = YALAPACK . gemlqt! (' R' , ' N' , A, T, one! (Q))
151+ Q = gemlqt! (driver, ' R' , ' N' , A, T, one! (Q))
171152 else
172- A, τ = YALAPACK . gelqf! (A)
153+ A, τ = gelqf! (driver, A)
173154 if inplaceQ
174- Q = YALAPACK . unglq! (A, τ)
155+ Q = unglq! (driver, A, τ)
175156 else
176- Q = YALAPACK . unmlq! (' R' , ' N' , A, τ, one! (Q))
157+ Q = unmlq! (driver, ' R' , ' N' , A, τ, one! (Q))
177158 end
178159 end
179160
180- if positive # already fix Q even if we do not need R
161+ if positive # already fix Q even if we do not need L
181162 @inbounds for j in 1 : n
182163 @simd for i in 1 : minmn
183164 s = sign_safe (A[i, i])
@@ -200,28 +181,102 @@ function _lapack_lq!(
200181 end
201182 return L, Q
202183end
203-
204- function _lapack_lq_null! (
205- A:: AbstractMatrix , Nᴴ:: AbstractMatrix ;
184+ function householder_lq_null! (
185+ driver:: LAPACK , A:: AbstractMatrix , Nᴴ:: AbstractMatrix ;
206186 positive = true , pivoted = false , blocksize = YALAPACK. default_qr_blocksize (A)
207187 )
208188 m, n = size (A)
209189 minmn = min (m, n)
210- fill ! (Nᴴ, zero ( eltype (Nᴴ)) )
190+ zero ! (Nᴴ)
211191 one! (view (Nᴴ, 1 : (n - minmn), (minmn + 1 ): n))
212192 if blocksize > 1
213193 mb = min (minmn, blocksize)
214- A, T = YALAPACK . gelqt! (A, similar (A, mb, minmn))
215- Nᴴ = YALAPACK . gemlqt! (' R' , ' N' , A, T, Nᴴ)
194+ A, T = gelqt! (driver, A, similar (A, mb, minmn))
195+ Nᴴ = gemlqt! (driver, ' R' , ' N' , A, T, Nᴴ)
216196 else
217- A, τ = YALAPACK. gelqf! (A)
218- Nᴴ = YALAPACK. unmlq! (' R' , ' N' , A, τ, Nᴴ)
197+ A, τ = gelqf! (driver, A)
198+ Nᴴ = unmlq! (driver, ' R' , ' N' , A, τ, Nᴴ)
199+ end
200+ return Nᴴ
201+ end
202+ function householder_lq! (
203+ :: Native , A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
204+ positive:: Bool = true # always true regardless of setting
205+ )
206+ m, n = size (A)
207+ minmn = min (m, n)
208+ @inbounds for i in 1 : minmn
209+ for j in 1 : (i - 1 )
210+ L[i, j] = A[i, j]
211+ end
212+ β, v, L[i, i] = _householder! (conj! (view (A, i, i: n)), 1 )
213+ for j in (i + 1 ): size (L, 2 )
214+ L[i, j] = 0
215+ end
216+ H = HouseholderReflection (conj (β), v, i: n)
217+ rmul! (A, H; rows = (i + 1 ): m)
218+ # A[i, i] == 1; store β instead
219+ A[i, i] = β
220+ end
221+ # copy remaining rows for m > n
222+ @inbounds for j in 1 : size (L, 2 )
223+ for i in (minmn + 1 ): m
224+ L[i, j] = A[i, j]
225+ end
226+ end
227+ # build Q
228+ one! (Q)
229+ @inbounds for i in minmn: - 1 : 1
230+ β = A[i, i]
231+ A[i, i] = 1
232+ Hᴴ = HouseholderReflection (β, view (A, i, i: n), i: n)
233+ rmul! (Q, Hᴴ)
234+ end
235+ return L, Q
236+ end
237+ function householder_lq_null! (:: Native , A:: AbstractMatrix , Nᴴ:: AbstractMatrix ; positive:: Bool = true )
238+ m, n = size (A)
239+ minmn = min (m, n)
240+ @inbounds for i in 1 : minmn
241+ β, v, ν = _householder! (conj! (view (A, i, i: n)), 1 )
242+ H = HouseholderReflection (conj (β), v, i: n)
243+ rmul! (A, H; rows = (i + 1 ): m)
244+ # A[i, i] == 1; store β instead
245+ A[i, i] = β
246+ end
247+ # build Nᴴ
248+ zero! (Nᴴ)
249+ one! (view (Nᴴ, 1 : (n - minmn), (minmn + 1 ): n))
250+ @inbounds for i in minmn: - 1 : 1
251+ β = A[i, i]
252+ A[i, i] = 1
253+ Hᴴ = HouseholderReflection (β, view (A, i, i: n), i: n)
254+ rmul! (Nᴴ, Hᴴ)
219255 end
220256 return Nᴴ
221257end
222258
259+
223260# LQ via transposition and QR
224261# ---------------------------
262+ function lq_full! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
263+ check_input (lq_full!, A, LQ, alg)
264+ L, Q = LQ
265+ lq_via_qr! (A, L, Q, alg. qr_alg)
266+ return L, Q
267+ end
268+ function lq_compact! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
269+ check_input (lq_compact!, A, LQ, alg)
270+ L, Q = LQ
271+ lq_via_qr! (A, L, Q, alg. qr_alg)
272+ return L, Q
273+ end
274+ function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LQViaTransposedQR )
275+ check_input (lq_null!, A, Nᴴ, alg)
276+ lq_null_via_qr! (A, Nᴴ, alg. qr_alg)
277+ return Nᴴ
278+ end
279+
225280function lq_via_qr! (
226281 A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix , qr_alg:: AbstractAlgorithm
227282 )
@@ -250,8 +305,26 @@ function lq_null_via_qr!(A::AbstractMatrix, N::AbstractMatrix, qr_alg::AbstractA
250305 return N
251306end
252307
253- # Diagonal logic
254- # --------------
308+
309+ # Diagonal
310+ # --------
311+ function lq_full! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
312+ check_input (lq_full!, A, LQ, alg)
313+ L, Q = LQ
314+ _diagonal_lq! (A, L, Q; alg. kwargs... )
315+ return L, Q
316+ end
317+ function lq_compact! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
318+ check_input (lq_compact!, A, LQ, alg)
319+ L, Q = LQ
320+ _diagonal_lq! (A, L, Q; alg. kwargs... )
321+ return L, Q
322+ end
323+ function lq_null! (A:: AbstractMatrix , N, alg:: DiagonalAlgorithm )
324+ check_input (lq_null!, A, N, alg)
325+ return _diagonal_lq_null! (A, N; alg. kwargs... )
326+ end
327+
255328function _diagonal_lq! (
256329 A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ; positive:: Bool = true
257330 )
@@ -271,84 +344,22 @@ end
271344
272345_diagonal_lq_null! (A:: AbstractMatrix , N; positive:: Bool = true ) = N
273346
274- # Native logic
275- # -------------
276- function lq_full! (A:: AbstractMatrix , LQ, alg:: Native_HouseholderLQ )
277- check_input (lq_full!, A, LQ, alg)
278- L, Q = LQ
279- A === Q &&
280- throw (ArgumentError (" inplace Q not supported with native LQ implementation" ))
281- _native_lq! (A, L, Q; alg. kwargs... )
282- return L, Q
283- end
284- function lq_compact! (A:: AbstractMatrix , LQ, alg:: Native_HouseholderLQ )
285- check_input (lq_compact!, A, LQ, alg)
286- L, Q = LQ
287- A === Q &&
288- throw (ArgumentError (" inplace Q not supported with native LQ implementation" ))
289- _native_lq! (A, L, Q; alg. kwargs... )
290- return L, Q
291- end
292- function lq_null! (A:: AbstractMatrix , N, alg:: Native_HouseholderLQ )
293- check_input (lq_null!, A, N, alg)
294- _native_lq_null! (A, N; alg. kwargs... )
295- return N
296- end
297-
298- function _native_lq! (
299- A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
300- positive:: Bool = true # always true regardless of setting
301- )
302- m, n = size (A)
303- minmn = min (m, n)
304- @inbounds for i in 1 : minmn
305- for j in 1 : (i - 1 )
306- L[i, j] = A[i, j]
307- end
308- β, v, L[i, i] = _householder! (conj! (view (A, i, i: n)), 1 )
309- for j in (i + 1 ): size (L, 2 )
310- L[i, j] = 0
311- end
312- H = Householder (conj (β), v, i: n)
313- rmul! (A, H; rows = (i + 1 ): m)
314- # A[i, i] == 1; store β instead
315- A[i, i] = β
316- end
317- # copy remaining rows for m > n
318- @inbounds for j in 1 : size (L, 2 )
319- for i in (minmn + 1 ): m
320- L[i, j] = A[i, j]
321- end
322- end
323- # build Q
324- one! (Q)
325- @inbounds for i in minmn: - 1 : 1
326- β = A[i, i]
327- A[i, i] = 1
328- Hᴴ = Householder (β, view (A, i, i: n), i: n)
329- rmul! (Q, Hᴴ)
330- end
331- return L, Q
332- end
333-
334- function _native_lq_null! (A:: AbstractMatrix , Nᴴ:: AbstractMatrix ; positive:: Bool = true )
335- m, n = size (A)
336- minmn = min (m, n)
337- @inbounds for i in 1 : minmn
338- β, v, ν = _householder! (conj! (view (A, i, i: n)), 1 )
339- H = Householder (conj (β), v, i: n)
340- rmul! (A, H; rows = (i + 1 ): m)
341- # A[i, i] == 1; store β instead
342- A[i, i] = β
343- end
344- # build Nᴴ
345- fill! (Nᴴ, zero (eltype (Nᴴ)))
346- one! (view (Nᴴ, 1 : (n - minmn), (minmn + 1 ): n))
347- @inbounds for i in minmn: - 1 : 1
348- β = A[i, i]
349- A[i, i] = 1
350- Hᴴ = Householder (β, view (A, i, i: n), i: n)
351- rmul! (Nᴴ, Hᴴ)
347+ # Deprecations
348+ # ------------
349+ for drivertype in (:LAPACK , :Native )
350+ algtype = Symbol (drivertype, :_HouseholderLQ )
351+ @eval begin
352+ Base. @deprecate (
353+ lq_full! (A, LQ, alg:: $algtype ),
354+ lq_full! (A, LQ, Householder ($ drivertype (), alg. kwargs))
355+ )
356+ Base. @deprecate (
357+ lq_compact! (A, LQ, alg:: $algtype ),
358+ lq_compact! (A, LQ, Householder ($ drivertype (), alg. kwargs))
359+ )
360+ Base. @deprecate (
361+ lq_null! (A, Nᴴ, alg:: $algtype ),
362+ lq_null! (A, Nᴴ, Householder ($ drivertype (), alg. kwargs))
363+ )
352364 end
353- return Nᴴ
354365end
0 commit comments