Skip to main content

a/math/matrix/
schur.rs

1//! The Schur decomposition: a blocked reduction to Hessenberg form, then the QR algorithm, in
2//! real arithmetic for real matrices: for small ones (below order 120, or 90 for complex ones
3//! with `Q`) Francis's double shifts (single shifts for complex ones), for larger ones the
4//! small-bulge multishift QR algorithm with aggressive early deflation, most of its work in
5//! products of blocks.
6
7use super::householder::{reflection, reflector};
8use super::properties::range_exponent;
9use super::{Matrix, Scalar};
10use crate::math::complex::{Complex, Float};
11
12mod deflate;
13mod hessenberg;
14mod multishift;
15mod vectors;
16
17pub(crate) use hessenberg::hessenberg;
18use multishift::multishift;
19pub(crate) use vectors::eigenvectors;
20
21/// The Schur decomposition `A = Q·T·Q*` of a square matrix, `Q` unitary (orthogonal for real
22/// elements). For complex elements `T` is upper triangular, its diagonal the eigenvalues. For
23/// real ones it is the real Schur form, quasi-upper triangular: blocks of `1 × 1` for the real
24/// eigenvalues and of `2 × 2` for the pairs of complex conjugate ones, each `[[a, b], [c, a]]`
25/// with `b·c < 0`, its eigenvalues `a ± i·√(-b·c)`. From [`Matrix::schur`].
26///
27/// # Examples
28///
29/// ```
30/// use a::math::complex::Complex;
31/// use a::math::matrix::Matrix;
32///
33/// // A rotation by a quarter turn: eigenvalues ±i, one 2 × 2 block.
34/// let a: Matrix<f64> = Matrix::from_rows(&[[0.0, -1.0], [1.0, 0.0]]);
35/// let s = a.schur();
36/// let back = &(&s.q() * &s.t()) * &s.q().transpose();
37/// assert!((&back - &a).as_slice().iter().all(|x| x.abs() < 1e-15));
38/// let mut values = s.eigenvalues().to_vec();
39/// values.sort_by(|a, b| a.im.total_cmp(&b.im));
40/// assert_eq!(values, [Complex::new(0.0, -1.0), Complex::new(0.0, 1.0)]);
41/// ```
42#[derive(Clone, Debug)]
43pub struct Schur<T: Scalar> {
44    /// `Q`.
45    q: Matrix<T>,
46    /// `T`.
47    t: Matrix<T>,
48    /// The eigenvalues, in the order of the diagonal of `T`.
49    values: Vec<Complex<T::Real>>,
50}
51
52impl<T: Scalar> Matrix<T> {
53    /// The Schur decomposition `A = Q·T·Q*`: see [`Schur`]. A reduction to Hessenberg form by
54    /// blocks of Householder reflections, then the QR algorithm with implicit shifts, for large
55    /// matrices many at a time with aggressive early deflation, about `25n³` operations. A
56    /// matrix with a NaN or an infinity gives NaNs.
57    ///
58    /// # Panics
59    ///
60    /// Panics if the matrix is not square.
61    #[track_caller]
62    pub fn schur(&self) -> Schur<T> {
63        assert!(self.is_square(), "the matrix is not square");
64        let (t, q, values) = schur(self, true, true);
65        Schur {
66            q: q.unwrap_or_default(),
67            t,
68            values,
69        }
70    }
71
72    /// The eigenvalues, in no particular order, those of a real matrix that are not real in
73    /// pairs of conjugates: the diagonal of the Schur form, computed without `Q`, so about
74    /// `10n³` operations. A matrix with a NaN or an infinity gives NaNs.
75    ///
76    /// # Panics
77    ///
78    /// Panics if the matrix is not square.
79    #[track_caller]
80    pub fn eigenvalues(&self) -> Vec<Complex<T::Real>> {
81        assert!(self.is_square(), "the matrix is not square");
82        schur(self, false, false).2
83    }
84}
85
86impl<T: Scalar> Schur<T> {
87    /// `Q`, unitary.
88    pub fn q(&self) -> Matrix<T> {
89        self.q.clone()
90    }
91
92    /// `T`, upper triangular, or quasi-upper triangular for real elements.
93    pub fn t(&self) -> Matrix<T> {
94        self.t.clone()
95    }
96
97    /// The eigenvalues, in the order of the diagonal of `T`; a pair of complex conjugates of a
98    /// real matrix, the one with the positive imaginary part first.
99    pub fn eigenvalues(&self) -> &[Complex<T::Real>] {
100        &self.values
101    }
102}
103
104/// The Schur form `T` of `a`, with `Q` when `want_q` is set, and the eigenvalues; only the
105/// eigenvalues are right in `T` when `want_t` is not set.
106#[allow(clippy::type_complexity)]
107pub(crate) fn schur<T: Scalar>(
108    a: &Matrix<T>,
109    want_t: bool,
110    want_q: bool,
111) -> (Matrix<T>, Option<Matrix<T>>, Vec<Complex<T::Real>>) {
112    let n = a.rows();
113    if a.data.iter().any(|x| !x.is_finite()) {
114        let nan = T::from_parts(T::Real::NAN, T::Real::NAN);
115        let all = Matrix::from_fn(n, n, |_, _| nan);
116        let w = vec![Complex::new(T::Real::NAN, T::Real::NAN); n];
117        return (all.clone(), want_q.then_some(all), w);
118    }
119    let mut h = a.clone();
120    // Scaled by a power of two when the largest element is so small or so large that the
121    // reduction or the QR algorithm could underflow or overflow, as LAPACK's `geev`: `T` and the
122    // eigenvalues scaled back, exactly, and `Q` the same.
123    let k = range_exponent(&h.data);
124    if k != 0 {
125        let up = T::Real::TWO.powi(k);
126        for x in &mut h.data {
127            *x = x.scale(up);
128        }
129    }
130    let mut q = hessenberg(&mut h, want_q);
131    let mut w = vec![Complex::new(T::Real::ZERO, T::Real::ZERO); n];
132    let z = q.as_mut().map(|q| q.data.as_mut_slice());
133    let info = multishift(want_t, &mut h.data, n, z, &mut w, false);
134    w[..info].fill(Complex::new(T::Real::NAN, T::Real::NAN));
135    if want_t && info == 0 {
136        // Zeros below the subdiagonal, and for complex elements on it.
137        for j in 0..n {
138            let from = if T::IS_COMPLEX { j + 1 } else { j + 2 };
139            for i in from..n {
140                h.data[i + j * n] = T::zero();
141            }
142        }
143    }
144    if k != 0 {
145        let down = T::Real::TWO.powi(-k);
146        for x in &mut h.data {
147            *x = x.scale(down);
148        }
149        for w in &mut w {
150            *w = Complex::new(w.re * down, w.im * down);
151        }
152    }
153    (h, q, w)
154}
155
156/// The QR algorithm with one or two shifts on the upper Hessenberg `h` of order `n`, as LAPACK's
157/// `lahqr`: in real arithmetic, Francis's double shifts, for real elements. The eigenvalues
158/// into `w`, `h` turned into the Schur form when `want_t` is set, the transformations
159/// accumulated into `z` when given. Returns the number of leading eigenvalues it didn't
160/// converge to, zero on success.
161fn small_qr<T: Scalar>(
162    h: &mut [T],
163    n: usize,
164    z: Option<&mut [T]>,
165    want_t: bool,
166    w: &mut [Complex<T::Real>],
167) -> usize {
168    if T::IS_COMPLEX {
169        return complex_qr(h, n, z, want_t, w);
170    }
171    let mut hr: Vec<T::Real> = h.iter().map(|x| x.re()).collect();
172    let mut zr: Option<Vec<T::Real>> = z.as_deref().map(|z| z.iter().map(|x| x.re()).collect());
173    let info = real_qr(&mut hr, n, zr.as_deref_mut(), want_t, w);
174    for (x, r) in h.iter_mut().zip(hr) {
175        *x = T::from_real(r);
176    }
177    if let (Some(z), Some(zr)) = (z, zr) {
178        for (x, r) in z.iter_mut().zip(zr) {
179            *x = T::from_real(r);
180        }
181    }
182    info
183}
184
185/// Every how many iterations without a deflation an exceptional shift is taken.
186const EXCEPTIONAL: usize = 10;
187
188/// `(c·x + s·y, c·y - s·x)`, a plane rotation.
189#[inline]
190fn rotate<R: Float>(x: &mut R, y: &mut R, c: R, s: R) {
191    let t = c * *x + s * *y;
192    *y = c * *y - s * *x;
193    *x = t;
194}
195
196/// The QR algorithm with Francis's implicit double shifts on the real upper Hessenberg `h`,
197/// as LAPACK's `lahqr`: the eigenvalues into `w`, `h` turned into the real Schur form when
198/// `want_t` is set, and the rotations accumulated into `z` when given. Returns the number of
199/// leading eigenvalues it didn't converge to.
200fn real_qr<R: Float>(
201    h: &mut [R],
202    n: usize,
203    mut z: Option<&mut [R]>,
204    want_t: bool,
205    w: &mut [Complex<R>],
206) -> usize {
207    let at = |i: usize, j: usize| i + j * n;
208    if n == 0 {
209        return 0;
210    }
211    let ulp = R::EPSILON;
212    let smlnum = R::MIN_POSITIVE * (R::from_f64(n as f64) / ulp);
213    let max_its = 30 * n.max(10);
214    let mut kdefl = 0;
215    // The active block is rows and columns `l..=i`.
216    let mut i = n - 1;
217    loop {
218        let mut l = 0;
219        let mut converged = false;
220        for _ in 0..=max_its {
221            // A negligible subdiagonal element splits the block.
222            let mut k = i;
223            while k > l {
224                let sub = h[at(k, k - 1)].abs();
225                if sub <= smlnum {
226                    break;
227                }
228                let mut tst = h[at(k - 1, k - 1)].abs() + h[at(k, k)].abs();
229                if tst == R::ZERO {
230                    if k >= 2 {
231                        tst += h[at(k - 1, k - 2)].abs();
232                    }
233                    if k + 1 < n {
234                        tst += h[at(k + 1, k)].abs();
235                    }
236                }
237                // Ahues and Tisseur's conservative test.
238                if sub <= ulp * tst {
239                    let up = h[at(k - 1, k)].abs();
240                    let (ab, ba) = (sub.max(up), sub.min(up));
241                    let d = (h[at(k - 1, k - 1)] - h[at(k, k)]).abs();
242                    let hk = h[at(k, k)].abs();
243                    let (aa, bb) = (hk.max(d), hk.min(d));
244                    let s = aa + ab;
245                    if ba * (ab / s) <= smlnum.max(ulp * (bb * (aa / s))) {
246                        break;
247                    }
248                }
249                k -= 1;
250            }
251            l = k;
252            if l > 0 {
253                h[at(l, l - 1)] = R::ZERO;
254            }
255            if l + 1 >= i {
256                converged = true;
257                break;
258            }
259            kdefl += 1;
260            let (i1, i2) = if want_t { (0, n - 1) } else { (l, i) };
261            // The shifts: the eigenvalues of the trailing 2 × 2 block, or exceptional ones.
262            let (h11, h12, h21, h22) = if kdefl % (2 * EXCEPTIONAL) == 0 {
263                let s = h[at(i, i - 1)].abs() + h[at(i - 1, i - 2)].abs();
264                let h11 = R::from_f64(0.75) * s + h[at(i, i)];
265                (h11, R::from_f64(-0.4375) * s, s, h11)
266            } else if kdefl % EXCEPTIONAL == 0 {
267                let s = h[at(l + 1, l)].abs() + h[at(l + 2, l + 1)].abs();
268                let h11 = R::from_f64(0.75) * s + h[at(l, l)];
269                (h11, R::from_f64(-0.4375) * s, s, h11)
270            } else {
271                (
272                    h[at(i - 1, i - 1)],
273                    h[at(i - 1, i)],
274                    h[at(i, i - 1)],
275                    h[at(i, i)],
276                )
277            };
278            let s = h11.abs() + h12.abs() + h21.abs() + h22.abs();
279            let (rt1r, rt1i, rt2r, rt2i);
280            if s == R::ZERO {
281                (rt1r, rt1i, rt2r, rt2i) = (R::ZERO, R::ZERO, R::ZERO, R::ZERO);
282            } else {
283                let (h11, h12, h21, h22) = (h11 / s, h12 / s, h21 / s, h22 / s);
284                let tr = (h11 + h22) * R::HALF;
285                let det = (h11 - tr) * (h22 - tr) - h12 * h21;
286                let rtdisc = det.abs().sqrt();
287                if det >= R::ZERO {
288                    rt1r = tr * s;
289                    rt2r = rt1r;
290                    rt1i = rtdisc * s;
291                    rt2i = -rt1i;
292                } else {
293                    // Two real shifts: both the one nearer `h22`.
294                    let (a, b) = (tr + rtdisc, tr - rtdisc);
295                    let r = if (a - h22).abs() <= (b - h22).abs() {
296                        a * s
297                    } else {
298                        b * s
299                    };
300                    (rt1r, rt2r, rt1i, rt2i) = (r, r, R::ZERO, R::ZERO);
301                }
302            }
303            // Where to start the sweep: two consecutive small subdiagonal elements.
304            let mut m = i - 2;
305            let mut v = [R::ZERO; 3];
306            loop {
307                let h21s = h[at(m + 1, m)];
308                let s = (h[at(m, m)] - rt2r).abs() + rt2i.abs() + h21s.abs();
309                let h21s = h21s / s;
310                v[0] = h21s * h[at(m, m + 1)] + (h[at(m, m)] - rt1r) * ((h[at(m, m)] - rt2r) / s)
311                    - rt1i * (rt2i / s);
312                v[1] = h21s * (h[at(m, m)] + h[at(m + 1, m + 1)] - rt1r - rt2r);
313                v[2] = h21s * h[at(m + 2, m + 1)];
314                let s = v[0].abs() + v[1].abs() + v[2].abs();
315                for x in &mut v {
316                    *x /= s;
317                }
318                if m == l {
319                    break;
320                }
321                let h00 = h[at(m, m - 1)].abs() * (v[1].abs() + v[2].abs());
322                let h01 = v[0].abs()
323                    * (h[at(m - 1, m - 1)].abs() + h[at(m, m)].abs() + h[at(m + 1, m + 1)].abs());
324                if h00 <= ulp * h01 {
325                    break;
326                }
327                m -= 1;
328            }
329            // The double-shift sweep, chasing the bulge down.
330            for k in m..i {
331                let nr = 3.min(i - k + 1);
332                if k > m {
333                    for p in 0..nr {
334                        v[p] = h[at(k + p, k - 1)];
335                    }
336                }
337                let (t1, beta) = {
338                    let (first, rest) = v.split_at_mut(1);
339                    real_reflector(first[0], &mut rest[..nr - 1])
340                };
341                v[0] = beta;
342                if k > m {
343                    h[at(k, k - 1)] = v[0];
344                    h[at(k + 1, k - 1)] = R::ZERO;
345                    if k + 2 < i + 1 {
346                        h[at(k + 2, k - 1)] = R::ZERO;
347                    }
348                } else if m > l {
349                    // Rather than negating it, which goes wrong when `v` underflows.
350                    h[at(k, k - 1)] = h[at(k, k - 1)] * (R::ONE - t1);
351                }
352                let v2 = v[1];
353                let t2 = t1 * v2;
354                if nr == 3 {
355                    let v3 = v[2];
356                    let t3 = t1 * v3;
357                    for j in k..=i2 {
358                        let sum = h[at(k, j)] + v2 * h[at(k + 1, j)] + v3 * h[at(k + 2, j)];
359                        h[at(k, j)] -= sum * t1;
360                        h[at(k + 1, j)] -= sum * t2;
361                        h[at(k + 2, j)] -= sum * t3;
362                    }
363                    for j in i1..=(k + 3).min(i) {
364                        let sum = h[at(j, k)] + v2 * h[at(j, k + 1)] + v3 * h[at(j, k + 2)];
365                        h[at(j, k)] -= sum * t1;
366                        h[at(j, k + 1)] -= sum * t2;
367                        h[at(j, k + 2)] -= sum * t3;
368                    }
369                    if let Some(z) = z.as_deref_mut() {
370                        for j in 0..n {
371                            let sum = z[at(j, k)] + v2 * z[at(j, k + 1)] + v3 * z[at(j, k + 2)];
372                            z[at(j, k)] -= sum * t1;
373                            z[at(j, k + 1)] -= sum * t2;
374                            z[at(j, k + 2)] -= sum * t3;
375                        }
376                    }
377                } else {
378                    for j in k..=i2 {
379                        let sum = h[at(k, j)] + v2 * h[at(k + 1, j)];
380                        h[at(k, j)] -= sum * t1;
381                        h[at(k + 1, j)] -= sum * t2;
382                    }
383                    for j in i1..=i {
384                        let sum = h[at(j, k)] + v2 * h[at(j, k + 1)];
385                        h[at(j, k)] -= sum * t1;
386                        h[at(j, k + 1)] -= sum * t2;
387                    }
388                    if let Some(z) = z.as_deref_mut() {
389                        for j in 0..n {
390                            let sum = z[at(j, k)] + v2 * z[at(j, k + 1)];
391                            z[at(j, k)] -= sum * t1;
392                            z[at(j, k + 1)] -= sum * t2;
393                        }
394                    }
395                }
396            }
397        }
398        if !converged {
399            return i + 1;
400        }
401        if l == i {
402            w[i] = Complex::new(h[at(i, i)], R::ZERO);
403        } else {
404            // A 2 × 2 block: its standard form, and the rotation that gives it.
405            let (a, b, c, d) = (
406                h[at(i - 1, i - 1)],
407                h[at(i - 1, i)],
408                h[at(i, i - 1)],
409                h[at(i, i)],
410            );
411            let s = standardize(a, b, c, d);
412            h[at(i - 1, i - 1)] = s.a;
413            h[at(i - 1, i)] = s.b;
414            h[at(i, i - 1)] = s.c;
415            h[at(i, i)] = s.d;
416            w[i - 1] = Complex::new(s.rt1r, s.rt1i);
417            w[i] = Complex::new(s.rt2r, s.rt2i);
418            if want_t {
419                for j in i + 1..n {
420                    let (x, y) = (h[at(i - 1, j)], h[at(i, j)]);
421                    let (mut x, mut y) = (x, y);
422                    rotate(&mut x, &mut y, s.cs, s.sn);
423                    h[at(i - 1, j)] = x;
424                    h[at(i, j)] = y;
425                }
426                for j in 0..i - 1 {
427                    let (mut x, mut y) = (h[at(j, i - 1)], h[at(j, i)]);
428                    rotate(&mut x, &mut y, s.cs, s.sn);
429                    h[at(j, i - 1)] = x;
430                    h[at(j, i)] = y;
431                }
432            }
433            if let Some(z) = z.as_deref_mut() {
434                for j in 0..n {
435                    let (mut x, mut y) = (z[at(j, i - 1)], z[at(j, i)]);
436                    rotate(&mut x, &mut y, s.cs, s.sn);
437                    z[at(j, i - 1)] = x;
438                    z[at(j, i)] = y;
439                }
440            }
441        }
442        kdefl = 0;
443        if l == 0 {
444            break;
445        }
446        i = l - 1;
447    }
448    0
449}
450
451/// The real reflection `I - τ·v·vᵀ`, `v = (1, x)`, taking `(alpha, x)` to `(β, 0)`: overwrites
452/// `x` with the rest of `v` and returns `(τ, β)`.
453fn real_reflector<R: Float>(alpha: R, x: &mut [R]) -> (R, R) {
454    let big = x.iter().fold(alpha.abs(), |m, v| m.max(v.abs()));
455    if moderate(big) {
456        let squares = x.iter().fold(R::ZERO, |s, v| s + *v * *v);
457        if squares == R::ZERO {
458            return (R::ZERO, alpha);
459        }
460        let beta = -(alpha * alpha + squares).sqrt().copysign(alpha);
461        return (real_reflection(alpha, beta, x), beta);
462    }
463    let mut scale = R::ZERO;
464    for v in x.iter() {
465        scale = scale.max(v.abs());
466    }
467    if scale == R::ZERO {
468        return (R::ZERO, alpha);
469    }
470    let mut s = R::ZERO;
471    for v in x.iter() {
472        let t = *v / scale;
473        s += t * t;
474    }
475    let xnorm = s.sqrt() * scale;
476    let beta = -alpha.hypot(xnorm).copysign(alpha);
477    // A norm below `MIN/ε` has lost digits to underflow: scaled up by a power of two and taken
478    // again, as `reflection` does.
479    let small = R::MIN_POSITIVE / R::EPSILON;
480    if beta.abs() < small {
481        let up = R::ONE / small;
482        for v in x.iter_mut() {
483            *v *= up;
484        }
485        let (tau, beta) = real_reflector(alpha * up, x);
486        return (tau, beta * small);
487    }
488    (real_reflection(alpha, beta, x), beta)
489}
490
491/// `τ`, with `x` scaled to the rest of `v`, of the real reflection taking `(alpha, x)` to
492/// `(β, 0)`: [`reflection`](super::householder::reflection) for real numbers, without its
493/// overflows near the largest float.
494fn real_reflection<R: Float>(alpha: R, beta: R, x: &mut [R]) -> R {
495    let d = alpha - beta;
496    if !d.is_finite() {
497        let r = R::ONE / (alpha * R::HALF - beta * R::HALF);
498        for v in x.iter_mut() {
499            *v = *v * r * R::HALF;
500        }
501    } else {
502        let r = R::ONE / d;
503        if r.is_finite() {
504            for v in x.iter_mut() {
505                *v *= r;
506            }
507        } else {
508            for v in x.iter_mut() {
509                *v /= d;
510            }
511        }
512    }
513    R::ONE - alpha / beta
514}
515
516/// A real 2 × 2 block in standard form, its eigenvalues and the rotation to it.
517struct Standard<R> {
518    a: R,
519    b: R,
520    c: R,
521    d: R,
522    rt1r: R,
523    rt1i: R,
524    rt2r: R,
525    rt2i: R,
526    cs: R,
527    sn: R,
528}
529
530/// The Schur form of the real block `[[a, b], [c, d]]`, as LAPACK's `lanv2`: upper triangular
531/// for real eigenvalues, `[[a, b], [c, a]]` with `b·c < 0` for complex ones, by the rotation
532/// `[[cs, -sn], [sn, cs]]`.
533fn standardize<R: Float>(mut a: R, mut b: R, mut c: R, mut d: R) -> Standard<R> {
534    let (mut cs, mut sn) = (R::ONE, R::ZERO);
535    let sign = |x: R, y: R| x.abs().copysign(y);
536    if c == R::ZERO {
537    } else if b == R::ZERO {
538        // Swap the rows and the columns.
539        cs = R::ZERO;
540        sn = R::ONE;
541        core::mem::swap(&mut a, &mut d);
542        b = -c;
543        c = R::ZERO;
544    } else if a - d == R::ZERO && b.is_sign_negative() != c.is_sign_negative() {
545    } else {
546        let temp = a - d;
547        let mut p = temp * R::HALF;
548        let bcmax = b.abs().max(c.abs());
549        let bcmis = b.abs().min(c.abs()) * sign(R::ONE, b) * sign(R::ONE, c);
550        let scale = p.abs().max(bcmax);
551        let mut z = (p / scale) * p + (bcmax / scale) * bcmis;
552        if z >= R::from_f64(4.0) * R::EPSILON {
553            // Real eigenvalues: `z` is their half difference.
554            z = p + sign(scale.sqrt() * z.sqrt(), p);
555            a = d + z;
556            d -= (bcmax / z) * bcmis;
557            let tau = c.hypot(z);
558            cs = z / tau;
559            sn = c / tau;
560            b -= c;
561            c = R::ZERO;
562        } else {
563            // Complex or nearly equal eigenvalues: equal diagonal elements.
564            let sigma = b + c;
565            let tau = sigma.hypot(temp);
566            cs = (R::HALF * (R::ONE + sigma.abs() / tau)).sqrt();
567            sn = -(temp * R::HALF / (tau * cs)) * sign(R::ONE, sigma);
568            let aa = a * cs + b * sn;
569            let bb = -a * sn + b * cs;
570            let cc = c * cs + d * sn;
571            let dd = -c * sn + d * cs;
572            a = aa * cs + cc * sn;
573            b = bb * cs + dd * sn;
574            c = -aa * sn + cc * cs;
575            d = -bb * sn + dd * cs;
576            let temp = R::HALF * (a + d);
577            a = temp;
578            d = temp;
579            if c != R::ZERO {
580                if b != R::ZERO {
581                    if b.is_sign_negative() == c.is_sign_negative() {
582                        // Real eigenvalues after all: upper triangular.
583                        let sab = b.abs().sqrt();
584                        let sac = c.abs().sqrt();
585                        p = sign(sab * sac, c);
586                        let tau = R::ONE / (b + c).abs().sqrt();
587                        a = temp + p;
588                        d = temp - p;
589                        b -= c;
590                        c = R::ZERO;
591                        let cs1 = sab * tau;
592                        let sn1 = sac * tau;
593                        let t = cs * cs1 - sn * sn1;
594                        sn = cs * sn1 + sn * cs1;
595                        cs = t;
596                    }
597                } else {
598                    b = -c;
599                    c = R::ZERO;
600                    let t = cs;
601                    cs = -sn;
602                    sn = t;
603                }
604            }
605        }
606    }
607    let (rt1i, rt2i) = if c == R::ZERO {
608        (R::ZERO, R::ZERO)
609    } else {
610        let r = b.abs().sqrt() * c.abs().sqrt();
611        (r, -r)
612    };
613    Standard {
614        a,
615        b,
616        c,
617        d,
618        rt1r: a,
619        rt1i,
620        rt2r: d,
621        rt2i,
622        cs,
623        sn,
624    }
625}
626
627/// `|re| + |im|`.
628#[inline]
629fn abs1<C: Scalar>(x: C) -> C::Real {
630    x.re().abs() + x.im().abs()
631}
632
633/// Whether the squares of numbers up to `big`, and their sums, neither overflow nor underflow
634/// harmfully.
635#[inline]
636fn moderate<R: Float>(big: R) -> bool {
637    let (low, high) = if R::MANTISSA_DIGITS > 24 {
638        (1e-130, 1e130)
639    } else {
640        (1e-15, 1e15)
641    };
642    R::from_f64(low) < big && big < R::from_f64(high)
643}
644
645/// [`reflector`] for the short vectors of the QR sweeps' bulges: the squares summed directly
646/// when they are [`moderate`].
647#[inline]
648fn short_reflector<C: Scalar>(alpha: C, x: &mut [C]) -> (C, C) {
649    let zero = C::Real::ZERO;
650    let big = x
651        .iter()
652        .fold(alpha.re().abs().max(alpha.im().abs()), |m, v| {
653            m.max(v.re().abs()).max(v.im().abs())
654        });
655    if !moderate(big) {
656        return reflector(alpha, x);
657    }
658    let squares = x.iter().fold(zero, |s, v| s + v.abs2());
659    if squares == zero && alpha.im() == zero {
660        return (C::zero(), alpha);
661    }
662    reflection(alpha, (alpha.abs2() + squares).sqrt(), x)
663}
664
665/// The QR algorithm with single implicit shifts on the complex upper Hessenberg `h`, as
666/// LAPACK's `lahqr` for complex matrices: the eigenvalues into `w`, `h` turned into the Schur
667/// form when `want_t` is set, the transformations accumulated into `z` when given. Returns the
668/// number of leading eigenvalues it didn't converge to.
669fn complex_qr<C: Scalar>(
670    h: &mut [C],
671    n: usize,
672    mut z: Option<&mut [C]>,
673    want_t: bool,
674    w: &mut [Complex<C::Real>],
675) -> usize {
676    let at = |i: usize, j: usize| i + j * n;
677    let zero = C::Real::ZERO;
678    if n == 0 {
679        return 0;
680    }
681    // Real subdiagonal elements, by a diagonal unitary similarity.
682    for i in 1..n {
683        let x = h[at(i, i - 1)];
684        if x.im() != zero {
685            let a = x.abs();
686            let sc = x.conj().scale(C::Real::ONE / a);
687            h[at(i, i - 1)] = C::from_real(a);
688            let jhi = n - 1;
689            for j in i..=jhi {
690                h[at(i, j)] *= sc;
691            }
692            for j in 0..=(i + 1).min(jhi) {
693                h[at(j, i)] *= sc.conj();
694            }
695            if let Some(z) = z.as_deref_mut() {
696                for j in 0..n {
697                    z[at(j, i)] *= sc.conj();
698                }
699            }
700        }
701    }
702    let ulp = C::Real::EPSILON;
703    let smlnum = C::Real::MIN_POSITIVE * (C::Real::from_f64(n as f64) / ulp);
704    let max_its = 30 * n.max(10);
705    let mut kdefl = 0;
706    let mut i = n - 1;
707    loop {
708        let mut l = 0;
709        let mut converged = false;
710        for _ in 0..=max_its {
711            let mut k = i;
712            while k > l {
713                let sub = abs1(h[at(k, k - 1)]);
714                if sub <= smlnum {
715                    break;
716                }
717                let mut tst = abs1(h[at(k - 1, k - 1)]) + abs1(h[at(k, k)]);
718                if tst == zero {
719                    if k >= 2 {
720                        tst += h[at(k - 1, k - 2)].re().abs();
721                    }
722                    if k + 1 < n {
723                        tst += h[at(k + 1, k)].re().abs();
724                    }
725                }
726                if h[at(k, k - 1)].re().abs() <= ulp * tst {
727                    let up = abs1(h[at(k - 1, k)]);
728                    let (ab, ba) = (sub.max(up), sub.min(up));
729                    let d = abs1(h[at(k - 1, k - 1)] - h[at(k, k)]);
730                    let hk = abs1(h[at(k, k)]);
731                    let (aa, bb) = (hk.max(d), hk.min(d));
732                    let s = aa + ab;
733                    if ba * (ab / s) <= smlnum.max(ulp * (bb * (aa / s))) {
734                        break;
735                    }
736                }
737                k -= 1;
738            }
739            l = k;
740            if l > 0 {
741                h[at(l, l - 1)] = C::zero();
742            }
743            if l >= i {
744                converged = true;
745                break;
746            }
747            kdefl += 1;
748            let (i1, i2) = if want_t { (0, n - 1) } else { (l, i) };
749            // The shift: Wilkinson's, or an exceptional one.
750            let t = if kdefl % (2 * EXCEPTIONAL) == 0 {
751                let s = C::Real::from_f64(0.75) * h[at(i, i - 1)].re().abs();
752                h[at(i, i)] + C::from_real(s)
753            } else if kdefl % EXCEPTIONAL == 0 {
754                let s = C::Real::from_f64(0.75) * h[at(l + 1, l)].re().abs();
755                h[at(l, l)] + C::from_real(s)
756            } else {
757                let mut t = h[at(i, i)];
758                let u = h[at(i - 1, i)].sqrt() * h[at(i, i - 1)].sqrt();
759                let s = abs1(u);
760                if s != zero {
761                    let x = (h[at(i - 1, i - 1)] - t).scale(C::Real::HALF);
762                    let sx = abs1(x);
763                    let s = s.max(sx);
764                    let (xs, us) = (x.scale(C::Real::ONE / s), u.scale(C::Real::ONE / s));
765                    let mut y = (xs * xs + us * us).sqrt().scale(s);
766                    if sx > zero {
767                        let xr = x.scale(C::Real::ONE / sx);
768                        if xr.re() * y.re() + xr.im() * y.im() < zero {
769                            y = -y;
770                        }
771                    }
772                    t -= u * (u / (x + y));
773                }
774                t
775            };
776            // Where to start: two consecutive small subdiagonal elements.
777            let mut m = i - 1;
778            let mut v: [C; 2];
779            loop {
780                let h11 = h[at(m, m)];
781                let h22 = h[at(m + 1, m + 1)];
782                let h11s = h11 - t;
783                let h21 = h[at(m + 1, m)].re();
784                let s = abs1(h11s) + h21.abs();
785                let (h11s, h21) = (h11s.scale(C::Real::ONE / s), h21 / s);
786                v = [h11s, C::from_real(h21)];
787                if m == l {
788                    break;
789                }
790                let h10 = h[at(m, m - 1)].re();
791                if h10.abs() * h21.abs() <= ulp * (abs1(h11s) * (abs1(h11) + abs1(h22))) {
792                    break;
793                }
794                m -= 1;
795            }
796            // The single-shift sweep.
797            for k in m..i {
798                if k > m {
799                    v = [h[at(k, k - 1)], h[at(k + 1, k - 1)]];
800                }
801                let (t1, beta) = {
802                    let (first, rest) = v.split_at_mut(1);
803                    short_reflector(first[0], rest)
804                };
805                v[0] = beta;
806                if k > m {
807                    h[at(k, k - 1)] = v[0];
808                    h[at(k + 1, k - 1)] = C::zero();
809                }
810                let v2 = v[1];
811                let t2 = (t1 * v2).re();
812                let (t1c, v2c) = (t1.conj(), v2.conj());
813                for col in h[k * n..(i2 + 1) * n].chunks_exact_mut(n) {
814                    let [x, y] = &mut col[k..k + 2] else {
815                        unreachable!()
816                    };
817                    let sum = t1c * *x + y.scale(t2);
818                    *x -= sum;
819                    *y -= sum * v2;
820                }
821                let turn = |a: &mut [C], rows: core::ops::Range<usize>| {
822                    let (x, y) = a[k * n..].split_at_mut(n);
823                    for (x, y) in x[rows.clone()].iter_mut().zip(&mut y[rows]) {
824                        let sum = t1 * *x + y.scale(t2);
825                        *x -= sum;
826                        *y -= sum * v2c;
827                    }
828                };
829                turn(h, i1..(k + 2).min(i) + 1);
830                if let Some(z) = z.as_deref_mut() {
831                    turn(z, 0..n);
832                }
833                if k == m && m > l {
834                    // Keep `h[m, m - 1]` real, the sweep having started below it.
835                    let mut temp = C::one() - t1;
836                    temp = temp.scale(C::Real::ONE / temp.abs());
837                    h[at(m + 1, m)] *= temp.conj();
838                    if m + 2 <= i {
839                        h[at(m + 2, m + 1)] *= temp;
840                    }
841                    for j in m..=i {
842                        if j != m + 1 {
843                            if i2 > j {
844                                for c in j + 1..=i2 {
845                                    h[at(j, c)] *= temp;
846                                }
847                            }
848                            for r in i1..j {
849                                h[at(r, j)] *= temp.conj();
850                            }
851                            if let Some(z) = z.as_deref_mut() {
852                                for r in 0..n {
853                                    z[at(r, j)] *= temp.conj();
854                                }
855                            }
856                        }
857                    }
858                }
859            }
860            // Keep `h[i, i - 1]` real.
861            let temp = h[at(i, i - 1)];
862            if temp.im() != zero {
863                let r = temp.abs();
864                h[at(i, i - 1)] = C::from_real(r);
865                let temp = temp.scale(C::Real::ONE / r);
866                if i2 > i {
867                    for c in i + 1..=i2 {
868                        h[at(i, c)] *= temp.conj();
869                    }
870                }
871                for r in i1..i {
872                    h[at(r, i)] *= temp;
873                }
874                if let Some(z) = z.as_deref_mut() {
875                    for r in 0..n {
876                        z[at(r, i)] *= temp;
877                    }
878                }
879            }
880        }
881        if !converged {
882            return i + 1;
883        }
884        w[i] = h[at(i, i)].to_complex();
885        kdefl = 0;
886        if l == 0 {
887            break;
888        }
889        i = l - 1;
890    }
891    0
892}