<T>LAPACK 0.1.2
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
lahqz_schur22.hpp
Go to the documentation of this file.
1
5//
6// Copyright (c) 2013-2022, University of Colorado Denver. All rights reserved.
7//
8// This file is part of <T>LAPACK.
9// <T>LAPACK is free software: you can redistribute it and/or modify it under
10// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
11
12#ifndef __TLAPACK_LAHQZ_SCHUR22_HH__
13#define __TLAPACK_LAHQZ_SCHUR22_HH__
14
16#include "tlapack/blas/rot.hpp"
17#include "tlapack/blas/rotg.hpp"
21namespace tlapack {
22
62template <TLAPACK_MATRIX A_t, TLAPACK_MATRIX B_t>
64 B_t& B,
75{
76 using TA = type_t<A_t>;
77 using real_t = real_type<TA>;
79
82
83 //
84 // Scale A
85 //
86 real_t anorm = max<real_t>(max<real_t>(abs1(A(0, 0)) + abs1(A(1, 0)),
87 abs1(A(0, 1)) + abs1(A(1, 1))),
88 safmin);
90 A(0, 0) *= ascale;
91 A(0, 1) *= ascale;
92 A(1, 0) *= ascale;
93 A(1, 1) *= ascale;
94 //
95 // Scale B
96 //
98 max<real_t>(abs1(B(0, 0)), abs1(B(0, 1)) + abs1(B(1, 1))), safmin);
100 B(0, 0) *= bscale;
101 B(0, 1) *= bscale;
102 B(1, 1) *= bscale;
103 //
104 // Check if A can be deflated
105 // Note, here we deviate from LAPACK by using elementwise instead of
106 // normwise.
107 //
108 real_t tst = abs1(A(0, 0)) + abs1(A(1, 1));
109 if (abs1(A(1, 0)) <= eps * tst) {
110 A(1, 0) = TA(0);
111
112 cl = real_t(1);
113 sl = TA(0);
114
115 cr = real_t(1);
116 sr = TA(0);
117 }
118 //
119 // Check if B is singular
120 // If it is, we can apply rotations to the right to make A(1,0) zero
121 // without perturbing the upper triangular structure of B
122 // Note, because of the scaling, we can just use an absolute threshold here
123 //
124 else if (abs1(B(0, 0)) <= eps) {
125 B(0, 0) = TA(0);
126 rotg(A(0, 0), A(1, 0), cl, sl);
127 A(1, 0) = TA(0);
128 TA temp = cl * A(0, 1) + sl * A(1, 1);
129 A(1, 1) = cl * A(1, 1) - conj(sl) * A(0, 1);
130 A(0, 1) = temp;
131 temp = cl * B(0, 1) + sl * B(1, 1);
132 B(1, 1) = cl * B(1, 1) - conj(sl) * B(0, 1);
133 B(0, 1) = temp;
134
135 cr = real_t(1);
136 sr = TA(0);
137 }
138 else if (abs1(B(1, 1)) <= eps) {
139 B(1, 1) = TA(0);
140 rotg(A(1, 1), A(1, 0), cr, sr);
141 A(1, 0) = TA(0);
142 TA temp = cr * A(0, 1) + sr * A(0, 0);
143 A(0, 0) = cr * A(0, 0) - conj(sr) * A(0, 1);
144 A(0, 1) = temp;
145 temp = cr * B(0, 1) + sr * B(0, 0);
146 B(0, 0) = cr * B(0, 0) - conj(sr) * B(0, 1);
147 B(0, 1) = temp;
148
149 sr = -conj(sr);
150
151 cl = real_t(1);
152 sl = TA(0);
153 }
154 else {
155 // A cannot be deflated and B is nonsingular
156 // Next step is to compute the generalized eigenvalues of the pencil
157 // (A,B)
159 if (is_complex<TA> or imag(alpha1) == real_t(0)) {
160 // We can further reduce the pencil into 2 1x1 blocks
161 // by applying rotations to the left and right
162
163 // Compute H = beta1*A - alpha1*B
164 TA h00, h01, h10, h11;
165 if constexpr (is_complex<TA>) {
166 h00 = beta1 * A(0, 0) - alpha1 * B(0, 0);
167 h01 = beta1 * A(0, 1) - alpha1 * B(0, 1);
168 h10 = beta1 * A(1, 0);
169 h11 = beta1 * A(1, 1) - alpha1 * B(1, 1);
170 }
171 else {
172 h00 = beta1 * A(0, 0) - real(alpha1) * B(0, 0);
173 h01 = beta1 * A(0, 1) - real(alpha1) * B(0, 1);
174 h10 = beta1 * A(1, 0);
175 h11 = beta1 * A(1, 1) - real(alpha1) * B(1, 1);
176 }
177
178 real_t rr;
179 if constexpr (is_complex<TA>) {
180 rr = lapy2(lapy2(real(h00), imag(h00)),
181 lapy2(real(h01), imag(h01)));
182 }
183 else {
184 rr = lapy2(h00, h01);
185 }
186
187 real_t qq;
188 if constexpr (is_complex<TA>) {
189 qq = lapy2(lapy2(real(h10), imag(h10)),
190 lapy2(real(h11), imag(h11)));
191 }
192 else {
193 qq = lapy2(h10, h11);
194 }
195
196 if (rr > qq) {
197 // Find right rotation matrix to zero 0,0 element
198 // of (sA - wB)
199 rotg(h01, h00, cr, sr);
200 }
201 else {
202 // Find right rotation matrix to zero 1,0 element
203 // of (sA - wB)
204 rotg(h11, h10, cr, sr);
205 }
206
207 // Apply the rotation to A, B, and form Z
208 TA temp;
209 temp = cr * A(0, 1) + sr * A(0, 0);
210 A(0, 0) = cr * A(0, 0) - conj(sr) * A(0, 1);
211 A(0, 1) = temp;
212 temp = cr * A(1, 1) + sr * A(1, 0);
213 A(1, 0) = cr * A(1, 0) - conj(sr) * A(1, 1);
214 A(1, 1) = temp;
215 temp = cr * B(0, 1) + sr * B(0, 0);
216 B(0, 0) = cr * B(0, 0) - conj(sr) * B(0, 1);
217 B(0, 1) = temp;
218 B(1, 0) = -conj(sr) * B(1, 1);
219 B(1, 1) = cr * B(1, 1);
220
221 sr = -conj(sr);
222
223 //
224 // Now make both A and B upper triangular by applying a left
225 // rotation
226 // It is hard to predict whether zeroing A(1,0) or B(1,0) will be
227 // more stable, so we try both and pick the one that gives the
228 // smallest error. Note: the normwise criterion used in LAPACK does
229 // not always work!
230 //
231 real_t Anrm = max<real_t>(abs1(A(0, 0)) + abs1(A(0, 1)),
232 abs1(A(1, 0)) + abs1(A(1, 1)));
233 real_t Bnrm = max<real_t>(abs1(B(0, 0)) + abs1(B(0, 1)),
234 abs1(B(1, 0)) + abs1(B(1, 1)));
235
236 real_t clA, clB;
237 TA slA, slB;
238
239 // Generate rotation based on A and calculate
240 // the resulting B(1,0)
241 TA tempA0 = A(0, 0);
242 TA tempA1 = A(1, 0);
244 TA eB10 = -conj(slA) * B(0, 0) + clA * B(1, 0);
245
246 TA tempB0 = B(0, 0);
247 TA tempB1 = B(1, 0);
249 TA eA10 = -conj(slB) * A(0, 0) + clB * A(1, 0);
250
251 if (abs1(eA10) * Bnrm <= abs1(eB10) * Anrm) {
252 cl = clB;
253 sl = slB;
254 B(0, 0) = tempB0;
255 A(0, 0) = cl * A(0, 0) + sl * A(1, 0);
256 }
257 else {
258 cl = clA;
259 sl = slA;
260 A(0, 0) = tempA0;
261 B(0, 0) = cl * B(0, 0) + sl * B(1, 0);
262 }
263 A(1, 0) = TA(0);
264 B(1, 0) = TA(0);
265
266 // Apply the rotation to A, B, and form Q
267 temp = cl * A(0, 1) + sl * A(1, 1);
268 A(1, 1) = cl * A(1, 1) - conj(sl) * A(0, 1);
269 A(0, 1) = temp;
270 temp = cl * B(0, 1) + sl * B(1, 1);
271 B(1, 1) = cl * B(1, 1) - conj(sl) * B(0, 1);
272 B(0, 1) = temp;
273 }
274 else {
275 if constexpr (is_real<TA>) {
276 // The pencil is real and has complex conjugate eigenvalues.
277 // It cannot be reduced further without using complex
278 // arithmetic. As normalization, we make B a diagonal matrix
279 // using a 2x2 SVD.
281 svd22<real_t>(B(0, 0), B(0, 1), B(1, 1), ssmin, ssmax, cl, sl,
282 cr, sr);
283 B(0, 0) = ssmax;
284 B(1, 1) = ssmin;
285 B(0, 1) = (real_t)0;
286 // Apply left rotation to A and form Q
287 TA temp;
288 temp = cl * A(0, 0) + sl * A(1, 0);
289 A(1, 0) = cl * A(1, 0) - sl * A(0, 0);
290 A(0, 0) = temp;
291 temp = cl * A(0, 1) + sl * A(1, 1);
292 A(1, 1) = cl * A(1, 1) - sl * A(0, 1);
293 A(0, 1) = temp;
294
295 // Apply right rotation to A and form Z
296 temp = cr * A(0, 0) + sr * A(0, 1);
297 A(0, 1) = cr * A(0, 1) - sr * A(0, 0);
298 A(0, 0) = temp;
299 temp = cr * A(1, 0) + sr * A(1, 1);
300 A(1, 1) = cr * A(1, 1) - sr * A(1, 0);
301 A(1, 0) = temp;
302 }
303 }
304 }
305
306 //
307 // Make sure the diagonal of B is non-negative and real
308 //
309 if constexpr (is_complex<TA>) {
310 // Multiply A and B by [conj(B00)/|B00|, 0; 0, conj(B11)/|B11|] to
311 // make B diagonal with non-negative entries
312 // To avoid overflow, we use rotg to compute the angle instead
313 // of the naive approach.
314 real_t br = real(B(0, 0));
315 real_t bi = imag(B(0, 0));
316 real_t c, s;
317 rotg(br, bi, c, s);
318 if (br < 0) {
319 br = -br;
320 c = -c;
321 s = -s;
322 }
323 scal0 = complex_t(c, -s);
324 B(0, 0) = br;
325 A(0, 0) *= scal0;
326 A(1, 0) *= scal0;
327
328 br = real(B(1, 1));
329 bi = imag(B(1, 1));
330 rotg(br, bi, c, s);
331 if (br < 0) {
332 br = -br;
333 c = -c;
334 s = -s;
335 }
336 scal1 = complex_t(c, -s);
337 B(1, 1) = br;
338 B(0, 1) *= scal1;
339 A(0, 1) *= scal1;
340 A(1, 1) *= scal1;
341 }
342 else {
343 // Ensure that the diagonal of B is non-negative
344 scal0 = TA(1);
345 scal1 = TA(1);
346 if (B(0, 0) < 0) {
347 B(0, 0) = -B(0, 0);
348 A(0, 0) = -A(0, 0);
349 A(1, 0) = -A(1, 0);
350 scal0 = TA(-1);
351 }
352 if (B(1, 1) < 0) {
353 B(0, 1) = -B(0, 1);
354 B(1, 1) = -B(1, 1);
355 A(0, 1) = -A(0, 1);
356 A(1, 1) = -A(1, 1);
357 scal1 = TA(-1);
358 }
359 }
360
361 // Undo scaling
362 A(0, 0) *= anorm;
363 A(0, 1) *= anorm;
364 A(1, 0) *= anorm;
365 A(1, 1) *= anorm;
366 B(0, 0) *= bnorm;
367 B(0, 1) *= bnorm;
368 B(1, 1) *= bnorm;
369 B(1, 0) *= bnorm;
370
371 if (A(1, 0) == TA(0)) {
372 alpha1 = A(0, 0);
373 beta1 = real(B(0, 0));
374 alpha2 = A(1, 1);
375 beta2 = real(B(1, 1));
376 }
377 else {
378 alpha1 *= anorm;
379 alpha2 *= anorm;
380 beta1 *= bnorm;
381 beta2 *= bnorm;
382 }
383}
384
385} // namespace tlapack
386
387#endif // __LAHQZ_SCHUR22_HH__
real_type< TX, TY > lapy2(const TX &x, const TY &y)
Finds , taking care not to cause unnecessary overflow.
Definition lapy2.hpp:34
void rotg(T &a, T &b, T &c, T &s)
Construct plane rotation that eliminates b, such that:
Definition rotg.hpp:39
Sort the numbers in D in increasing order (if ID = 'I') or in decreasing order (if ID = 'D' ).
Definition arrayTraits.hpp:15
typename traits::real_type_traits< Types..., int >::type real_type
The common real type of the list of types.
Definition scalar_type_traits.hpp:113
constexpr real_type< T > real(const T &x) noexcept
Extends std::real() to real datatypes.
Definition utils.hpp:71
constexpr T conj(const T &x) noexcept
Extends std::conj() to real datatypes.
Definition utils.hpp:100
constexpr real_type< T > abs1(const T &x)
1-norm absolute value, |Re(x)| + |Im(x)|
Definition utils.hpp:133
void lahqz_schur22(A_t &A, B_t &B, complex_type< type_t< A_t > > &alpha1, complex_type< type_t< A_t > > &alpha2, real_type< type_t< A_t > > &beta1, real_type< type_t< A_t > > &beta2, real_type< type_t< A_t > > &cl, type_t< A_t > &sl, real_type< type_t< A_t > > &cr, type_t< A_t > &sr, type_t< A_t > &scal0, type_t< A_t > &scal1)
Computes the generalized Schur factorization of a 2x2 pencil (A,B) with B upper triangular.
Definition lahqz_schur22.hpp:63
constexpr real_type< T > imag(const T &x) noexcept
Extends std::imag() to real datatypes.
Definition utils.hpp:86
typename traits::complex_type_traits< Types..., int >::type complex_type
The common complex type of the list of types.
Definition scalar_type_traits.hpp:188
void lahqz_eig22(const A_t &A, const B_t &B, complex_type< T > &alpha1, complex_type< T > &alpha2, T &beta1, T &beta2)
Computes the generalized eigenvalues of a 2x2 pencil (A,B) with B upper triangular.
Definition lahqz_eig22.hpp:33