11# Inputs
22# ------
3- function copy_input (:: typeof (lq_full), A:: AbstractMatrix )
4- return copy! (similar (A, float (eltype (A))), A)
5- end
6- function copy_input (:: typeof (lq_compact), A:: AbstractMatrix )
7- return copy! (similar (A, float (eltype (A))), A)
8- end
9- function copy_input (:: typeof (lq_null), A:: AbstractMatrix )
10- return copy! (similar (A, float (eltype (A))), A)
3+ for f in (:lq_full , :lq_compact , :lq_null )
4+ @eval function copy_input (:: typeof ($ f), A:: AbstractMatrix )
5+ return copy! (similar (A, float (eltype (A))), A)
6+ end
7+ @eval copy_input (:: typeof ($ f), A:: Diagonal ) = copy (A)
118end
129
1310function check_input (:: typeof (lq_full!), A:: AbstractMatrix , LQ, :: AbstractAlgorithm )
@@ -40,6 +37,28 @@ function check_input(::typeof(lq_null!), A::AbstractMatrix, Nᴴ, ::AbstractAlgo
4037 return nothing
4138end
4239
40+ function check_input (:: typeof (lq_full!), A:: AbstractMatrix , (L, Q), :: DiagonalAlgorithm )
41+ m, n = size (A)
42+ @assert m == n && isdiag (A)
43+ @assert Q isa Diagonal && L isa Diagonal
44+ isempty (L) || @check_size (L, (m, n))
45+ @check_scalar (L, A)
46+ @check_size (Q, (n, n))
47+ @check_scalar (Q, A)
48+ return nothing
49+ end
50+ function check_input (:: typeof (lq_compact!), A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
51+ return check_input (lq_full!, A, LQ, alg)
52+ end
53+ function check_input (:: typeof (lq_null!), A:: AbstractMatrix , N, :: DiagonalAlgorithm )
54+ m, n = size (A)
55+ @assert m == n && isdiag (A)
56+ @assert N isa AbstractMatrix
57+ @check_size (N, (0 , m))
58+ @check_scalar (N, A)
59+ return nothing
60+ end
61+
4362# Outputs
4463# -------
4564function initialize_output (:: typeof (lq_full!), A:: AbstractMatrix , :: AbstractAlgorithm )
@@ -62,44 +81,69 @@ function initialize_output(::typeof(lq_null!), A::AbstractMatrix, ::AbstractAlgo
6281 return Nᴴ
6382end
6483
84+ for f! in (:lq_full! , :lq_compact! )
85+ @eval function initialize_output (:: typeof ($ f!), A:: AbstractMatrix , :: DiagonalAlgorithm )
86+ return similar (A), A
87+ end
88+ end
89+
6590# Implementation
6691# --------------
67- # actual implementation
6892function lq_full! (A:: AbstractMatrix , LQ, alg:: LAPACK_HouseholderLQ )
6993 check_input (lq_full!, A, LQ, alg)
7094 L, Q = LQ
7195 _lapack_lq! (A, L, Q; alg. kwargs... )
7296 return L, Q
7397end
74- function lq_full! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
75- check_input (lq_full!, A, LQ, alg)
76- L, Q = LQ
77- lq_via_qr! (A, L, Q, alg. qr_alg)
78- return L, Q
79- end
8098function lq_compact! (A:: AbstractMatrix , LQ, alg:: LAPACK_HouseholderLQ )
8199 check_input (lq_compact!, A, LQ, alg)
82100 L, Q = LQ
83101 _lapack_lq! (A, L, Q; alg. kwargs... )
84102 return L, Q
85103end
104+ function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LAPACK_HouseholderLQ )
105+ check_input (lq_null!, A, Nᴴ, alg)
106+ _lapack_lq_null! (A, Nᴴ; alg. kwargs... )
107+ return Nᴴ
108+ end
109+
110+ function lq_full! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
111+ check_input (lq_full!, A, LQ, alg)
112+ L, Q = LQ
113+ lq_via_qr! (A, L, Q, alg. qr_alg)
114+ return L, Q
115+ end
86116function lq_compact! (A:: AbstractMatrix , LQ, alg:: LQViaTransposedQR )
87117 check_input (lq_compact!, A, LQ, alg)
88118 L, Q = LQ
89119 lq_via_qr! (A, L, Q, alg. qr_alg)
90120 return L, Q
91121end
92- function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LAPACK_HouseholderLQ )
93- check_input (lq_null!, A, Nᴴ, alg)
94- _lapack_lq_null! (A, Nᴴ; alg. kwargs... )
95- return Nᴴ
96- end
97122function lq_null! (A:: AbstractMatrix , Nᴴ, alg:: LQViaTransposedQR )
98123 check_input (lq_null!, A, Nᴴ, alg)
99124 lq_null_via_qr! (A, Nᴴ, alg. qr_alg)
100125 return Nᴴ
101126end
102127
128+ function lq_full! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
129+ check_input (lq_full!, A, LQ, alg)
130+ L, Q = LQ
131+ _diagonal_lq! (A, L, Q; alg. kwargs... )
132+ return L, Q
133+ end
134+ function lq_compact! (A:: AbstractMatrix , LQ, alg:: DiagonalAlgorithm )
135+ check_input (lq_compact!, A, LQ, alg)
136+ L, Q = LQ
137+ _diagonal_lq! (A, L, Q; alg. kwargs... )
138+ return L, Q
139+ end
140+ function lq_null! (A:: AbstractMatrix , N, alg:: DiagonalAlgorithm )
141+ check_input (lq_null!, A, N, alg)
142+ return _diagonal_lq_null! (A, N; alg. kwargs... )
143+ end
144+
145+ # LAPACK logic
146+ # ------------
103147function _lapack_lq! (A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
104148 positive= false ,
105149 pivoted= false ,
@@ -177,6 +221,7 @@ function _lapack_lq_null!(A::AbstractMatrix, Nᴴ::AbstractMatrix;
177221end
178222
179223# LQ via transposition and QR
224+ # ---------------------------
180225function lq_via_qr! (A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ,
181226 qr_alg:: AbstractAlgorithm )
182227 m, n = size (A)
@@ -203,3 +248,23 @@ function lq_null_via_qr!(A::AbstractMatrix, N::AbstractMatrix, qr_alg::AbstractA
203248 ! isempty (N) && adjoint! (N, Nt)
204249 return N
205250end
251+
252+ # Diagonal logic
253+ # --------------
254+ function _diagonal_lq! (A:: AbstractMatrix , L:: AbstractMatrix , Q:: AbstractMatrix ;
255+ positive:: Bool = false )
256+ # note: Ad and Qd might share memory here so order of operations is important
257+ Ad = diagview (A)
258+ Ld = diagview (L)
259+ Qd = diagview (Q)
260+ if positive
261+ @. Ld = abs (Ad)
262+ @. Qd = sign_safe (Ad)
263+ else
264+ Ld .= Ad
265+ one! (Q)
266+ end
267+ return L, Q
268+ end
269+
270+ _diagonal_lq_null! (A:: AbstractMatrix , N; positive:: Bool = false ) = N
0 commit comments