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