8181
8282# Implementation of orth functions
8383# --------------------------------
84- function left_orth! (A:: AbstractMatrix , VC; kwargs... )
84+ function left_orth! (A:: AbstractMatrix , VC; trunc= nothing ,
85+ kind= isnothing (trunc) ? :qr : :svd , alg_qr= (; positive= true ),
86+ alg_polar= (;), alg_svd= (;))
8587 check_input (left_orth!, A, VC)
86- atol = get (kwargs, :atol , 0 )
87- rtol = get (kwargs, :rtol , 0 )
88- kind = get (kwargs, :kind , iszero (atol) && iszero (rtol) ? :qrpos : :svd )
89- if ! (iszero (atol) && iszero (rtol)) && kind != :svd
90- throw (ArgumentError (" nonzero tolerance not supported for left_orth with kind=$kind " ))
88+ if ! isnothing (trunc) && kind != :svd
89+ throw (ArgumentError (" truncation not supported for left_orth with kind=$kind " ))
9190 end
9291 if kind == :qr
93- alg = get (kwargs, :alg , select_algorithm (qr_compact!, A))
94- return qr_compact! (A, VC, alg)
95- elseif kind == :qrpos
96- alg = get (kwargs, :alg , select_algorithm (qr_compact!, A; positive= true ))
97- return qr_compact! (A, VC, alg)
92+ alg_qr′ = _select_algorithm (qr_compact!, A, alg_qr)
93+ return qr_compact! (A, VC, alg_qr′)
9894 elseif kind == :polar
9995 size (A, 1 ) >= size (A, 2 ) ||
10096 throw (ArgumentError (" `left_orth!` with `kind = :polar` only possible for `(m, n)` matrix with `m >= n`" ))
101- alg = get (kwargs, :alg , select_algorithm ( left_polar!, A) )
102- return left_polar! (A, VC, alg )
103- elseif kind == :svd && iszero (atol) && iszero (rtol )
104- alg = get (kwargs, :alg , select_algorithm ( svd_compact!, A) )
97+ alg_polar′ = _select_algorithm ( left_polar!, A, alg_polar )
98+ return left_polar! (A, VC, alg_polar′ )
99+ elseif kind == :svd && isnothing (trunc )
100+ alg_svd′ = _select_algorithm ( svd_compact!, A, alg_svd )
105101 V, C = VC
106- S = Diagonal (initialize_output (svd_vals!, A, alg ))
107- U, S, Vᴴ = svd_compact! (A, (V, S, C), alg )
102+ S = Diagonal (initialize_output (svd_vals!, A, alg_svd′ ))
103+ U, S, Vᴴ = svd_compact! (A, (V, S, C), alg_svd′ )
108104 return U, lmul! (S, Vᴴ)
109105 elseif kind == :svd
110- alg_svd = select_algorithm (svd_compact!, A)
111- trunc = TruncationKeepAbove (atol, rtol)
112- alg = get (kwargs, :alg , TruncatedAlgorithm (alg_svd, trunc))
106+ alg_svd′ = _select_algorithm (svd_compact!, A, alg_svd)
107+ alg_svd_trunc = select_algorithm (svd_trunc!, A; trunc, alg= alg_svd′)
113108 V, C = VC
114- S = Diagonal (initialize_output (svd_vals!, A, alg_svd ))
115- U, S, Vᴴ = svd_trunc! (A, (V, S, C), alg )
109+ S = Diagonal (initialize_output (svd_vals!, A, alg_svd_trunc . alg ))
110+ U, S, Vᴴ = svd_trunc! (A, (V, S, C), alg_svd_trunc )
116111 return U, lmul! (S, Vᴴ)
117112 else
118113 throw (ArgumentError (" `left_orth!` received unknown value `kind = $kind `" ))
119114 end
120115end
121116
122- function right_orth! (A:: AbstractMatrix , CVᴴ; kwargs... )
117+ function right_orth! (A:: AbstractMatrix , CVᴴ; trunc= nothing ,
118+ kind= isnothing (trunc) ? :lq : :svd , alg_lq= (; positive= true ),
119+ alg_polar= (;), alg_svd= (;))
123120 check_input (right_orth!, A, CVᴴ)
124- atol = get (kwargs, :atol , 0 )
125- rtol = get (kwargs, :rtol , 0 )
126- kind = get (kwargs, :kind , iszero (atol) && iszero (rtol) ? :lqpos : :svd )
127- if ! (iszero (atol) && iszero (rtol)) && kind != :svd
128- throw (ArgumentError (" nonzero tolerance not supported for left_orth with kind=$kind " ))
121+ if ! isnothing (trunc) && kind != :svd
122+ throw (ArgumentError (" truncation not supported for right_orth with kind=$kind " ))
129123 end
130124 if kind == :lq
131- alg = get (kwargs, :alg , select_algorithm (lq_compact!, A))
132- return lq_compact! (A, CVᴴ, alg)
133- elseif kind == :lqpos
134- alg = get (kwargs, :alg , select_algorithm (lq_compact!, A; positive= true ))
135- return lq_compact! (A, CVᴴ, alg)
125+ alg_lq′ = _select_algorithm (lq_compact!, A, alg_lq)
126+ return lq_compact! (A, CVᴴ, alg_lq′)
136127 elseif kind == :polar
137128 size (A, 2 ) >= size (A, 1 ) ||
138129 throw (ArgumentError (" `right_orth!` with `kind = :polar` only possible for `(m, n)` matrix with `m <= n`" ))
139- alg = get (kwargs, :alg , select_algorithm ( right_polar!, A) )
140- return right_polar! (A, CVᴴ, alg )
141- elseif kind == :svd && iszero (atol) && iszero (rtol )
142- alg = get (kwargs, :alg , select_algorithm ( svd_compact!, A) )
130+ alg_polar′ = _select_algorithm ( right_polar!, A, alg_polar )
131+ return right_polar! (A, CVᴴ, alg_polar′ )
132+ elseif kind == :svd && isnothing (trunc )
133+ alg_svd′ = _select_algorithm ( svd_compact!, A, alg_svd )
143134 C, Vᴴ = CVᴴ
144- S = Diagonal (initialize_output (svd_vals!, A, alg ))
145- U, S, Vᴴ = svd_compact! (A, (C, S, Vᴴ), alg )
135+ S = Diagonal (initialize_output (svd_vals!, A, alg_svd′ ))
136+ U, S, Vᴴ = svd_compact! (A, (C, S, Vᴴ), alg_svd′ )
146137 return rmul! (U, S), Vᴴ
147138 elseif kind == :svd
148- alg_svd = select_algorithm (svd_compact!, A)
149- trunc = TruncationKeepAbove (atol, rtol)
150- alg = get (kwargs, :alg , TruncatedAlgorithm (alg_svd, trunc))
139+ alg_svd′ = _select_algorithm (svd_compact!, A, alg_svd)
140+ alg_svd_trunc = select_algorithm (svd_trunc!, A; trunc, alg= alg_svd′)
151141 C, Vᴴ = CVᴴ
152- S = Diagonal (initialize_output (svd_vals!, A, alg_svd ))
153- U, S, Vᴴ = svd_trunc! (A, (C, S, Vᴴ), alg )
142+ S = Diagonal (initialize_output (svd_vals!, A, alg_svd_trunc . alg ))
143+ U, S, Vᴴ = svd_trunc! (A, (C, S, Vᴴ), alg_svd_trunc )
154144 return rmul! (U, S), Vᴴ
155145 else
156146 throw (ArgumentError (" `right_orth!` received unknown value `kind = $kind `" ))
@@ -159,59 +149,65 @@ end
159149
160150# Implementation of null functions
161151# --------------------------------
162- function left_null! (A:: AbstractMatrix , N; kwargs... )
152+ function null_truncation_strategy (; atol= nothing , rtol= nothing , maxnullity= nothing )
153+ if isnothing (maxnullity) && isnothing (atol) && isnothing (rtol)
154+ return NoTruncation ()
155+ end
156+ atol = @something atol 0
157+ rtol = @something rtol 0
158+ trunc = TruncationKeepBelow (atol, rtol)
159+ return ! isnothing (maxnullity) ? trunc & truncrank (maxnullity; rev= false ) : trunc
160+ end
161+
162+ function left_null! (A:: AbstractMatrix , N; trunc= nothing ,
163+ kind= isnothing (trunc) ? :qr : :svd , alg_qr= (; positive= true ),
164+ alg_svd= (;))
163165 check_input (left_null!, A, N)
164- atol = get (kwargs, :atol , 0 )
165- rtol = get (kwargs, :rtol , 0 )
166- kind = get (kwargs, :kind , iszero (atol) && iszero (rtol) ? :qrpos : :svd )
167- if ! (iszero (atol) && iszero (rtol)) && kind != :svd
168- throw (ArgumentError (" nonzero tolerance not supported for left_orth with kind=$kind " ))
166+ if ! isnothing (trunc) && kind != :svd
167+ throw (ArgumentError (" truncation not supported for left_null with kind=$kind " ))
169168 end
170169 if kind == :qr
171- alg = get (kwargs, :alg , select_algorithm (qr_null!, A))
172- return qr_null! (A, N, alg)
173- elseif kind == :qrpos
174- alg = get (kwargs, :alg , select_algorithm (qr_null!, A; positive= true ))
175- return qr_null! (A, N, alg)
176- elseif kind == :svd && iszero (atol) && iszero (rtol)
177- alg = get (kwargs, :alg , select_algorithm (svd_full!, A))
178- U, _, _ = svd_full! (A, alg)
170+ alg_qr′ = _select_algorithm (qr_null!, A, alg_qr)
171+ return qr_null! (A, N, alg_qr′)
172+ elseif kind == :svd && isnothing (trunc)
173+ alg_svd′ = _select_algorithm (svd_full!, A, alg_svd)
174+ U, _, _ = svd_full! (A, alg_svd′)
179175 (m, n) = size (A)
180176 return copy! (N, view (U, 1 : m, (n + 1 ): m))
181177 elseif kind == :svd
182- alg = get (kwargs, :alg , select_algorithm (svd_full!, A))
183- U, S, _ = svd_full! (A, alg)
184- trunc = TruncationKeepBelow (atol, rtol)
185- return truncate! (left_null!, (U, S), trunc)
178+ alg_svd′ = _select_algorithm (svd_full!, A, alg_svd)
179+ U, S, _ = svd_full! (A, alg_svd′)
180+ trunc′ = trunc isa TruncationStrategy ? trunc :
181+ trunc isa NamedTuple ? null_truncation_strategy (; trunc... ) :
182+ throw (ArgumentError (" Unknown truncation strategy: $trunc " ))
183+ return truncate! (left_null!, (U, S), trunc′)
186184 else
187185 throw (ArgumentError (" `left_null!` received unknown value `kind = $kind `" ))
188186 end
189187end
190188
191- function right_null! (A:: AbstractMatrix , Nᴴ; kwargs... )
189+ function right_null! (A:: AbstractMatrix , Nᴴ; trunc= nothing ,
190+ kind= isnothing (trunc) ? :lq : :svd , alg_lq= (; positive= true ),
191+ alg_svd= (;))
192192 check_input (right_null!, A, Nᴴ)
193- atol = get (kwargs, :atol , 0 )
194- rtol = get (kwargs, :rtol , 0 )
195- kind = get (kwargs, :kind , iszero (atol) && iszero (rtol) ? :lqpos : :svd )
196- if ! (iszero (atol) && iszero (rtol)) && kind != :svd
197- throw (ArgumentError (" nonzero tolerance not supported for left_orth with kind=$kind " ))
193+ if ! isnothing (trunc) && kind != :svd
194+ throw (ArgumentError (" truncation not supported for right_null with kind=$kind " ))
198195 end
199196 if kind == :lq
200- alg = get (kwargs, :alg , select_algorithm (lq_null!, A))
201- return lq_null! (A, Nᴴ, alg)
202- elseif kind == :lqpos
203- alg = get (kwargs, :alg , select_algorithm (lq_null!, A; positive= true ))
204- return lq_null! (A, Nᴴ, alg)
205- elseif kind == :svd && iszero (atol) && iszero (rtol)
206- alg = get (kwargs, :alg , select_algorithm (svd_full!, A))
207- _, _, Vᴴ = svd_full! (A, alg)
197+ alg_lq′ = _select_algorithm (lq_null!, A, alg_lq)
198+ return lq_null! (A, Nᴴ, alg_lq′)
199+ elseif kind == :svd && isnothing (trunc)
200+ alg_svd′ = _select_algorithm (svd_full!, A, alg_svd)
201+ _, _, Vᴴ = svd_full! (A, alg_svd′)
208202 (m, n) = size (A)
209203 return copy! (Nᴴ, view (Vᴴ, (m + 1 ): n, 1 : n))
210204 elseif kind == :svd
211- alg = get (kwargs, :alg , select_algorithm (svd_full!, A))
212- _, S, Vᴴ = svd_full! (A, alg)
213- trunc = TruncationKeepBelow (atol, rtol)
214- return truncate! (right_null!, (S, Vᴴ), trunc)
205+ alg_svd′ = _select_algorithm (svd_full!, A, alg_svd)
206+ _, S, Vᴴ = svd_full! (A, alg_svd′)
207+ trunc′ = trunc isa TruncationStrategy ? trunc :
208+ trunc isa NamedTuple ? null_truncation_strategy (; trunc... ) :
209+ throw (ArgumentError (" Unknown truncation strategy: $trunc " ))
210+ return truncate! (right_null!, (S, Vᴴ), trunc′)
215211 else
216212 throw (ArgumentError (" `right_null!` received unknown value `kind = $kind `" ))
217213 end
0 commit comments