package Jampack; /** Schur implements the Schur decomposition of a matrix. Specifically, given a square matrix A, there is a unitary matrix U such that
*      T = U^H AU
is upper triangular. Schur represents T as a Zutmat and U as a Zmat. @version Pre-alpha @author G. W. Stewart */ public class Schur{ /** The upper triangular matrix. */ public Zutmat T; /** The unitary matrix. */ public Zmat U; /** Limits the number of interations in the QR algorithm */ public static int MAXITER = 30; /** Creats a Schur decomposition from a square Zmat. @param A The Zmat whose Schur decomposition is to be computed @exception JampackException Thrown for nonsquare matrix.
Thrown for maximum iteration count exceeded. */ public Schur(Zmat A) throws JampackException{ int i, il, iter, iu, k; double d, sd, sf; Z b = new Z(), c = new Z(), disc = new Z(), kappa = new Z(), p, q, r, r1 = new Z(), r2 = new Z(), s, z1 = new Z(), z2 = new Z(); Rot P = new Rot(); if (A.nr != A.nc){ throw new JampackException ("Nonsquare matrix"); } /* Reduce to Hessenberg form and set up T and U */ Zhess H = new Zhess(A); T = new Zutmat(H.H); U = H.U; iu = T.rx; iter = 0; while(true){ // Locate the range in which to iterate. while (iu > T.bx){ d = Z.abs1(T.get(iu,iu)) + Z.abs1(T.get(iu-1,iu-1)); sd = Z.abs1(T.get(iu,iu-1)); if (sd >= 1.0e-16*d) break; T.put(iu, iu-1, Z.ZERO); iter = 0; iu = iu-1; } if (iu == T.bx) break; iter = iter+1; if (iter >= MAXITER){ throw new JampackException ("Maximum number of iterations exceeded."); } il = iu-1; while (il > T.bx){ d = Z.abs1(T.get(il,il)) + Z.abs1(T.get(il-1,il-1)); sd = Z.abs1(T.get(il,il-1)); if (sd < 1.0e-16*d) break; il = il-1; } if(il != T.bx){ T.put(il, il-1, Z.ZERO); } // Compute the shift. p = T.get(iu-1,iu-1); q = T.get(iu-1,iu); r = T.get(iu,iu-1); s = T.get(iu,iu); sf = Z.abs1(p) + Z.abs1(q) + Z.abs1(r) + Z.abs1(s); p.Div(p, sf); q.Div(q, sf); r.Div(r, sf); s.Div(s, sf); c.Minus(z1.Times(p, s), z2.Times(r, q)); b.Plus(p, s); disc.Sqrt(disc.Minus(z1.Times(b,b), z2.Times(4,c))); r1.Div(r1.Plus(b, disc), 2); r2.Div(r2.Minus(b, disc), 2); if (Z.abs1(r1) > Z.abs1(r2)){ r2.Div(c, r1); } else{ r1.Div(c, r2); } if (Z.abs1(z1.Minus(r1, s)) < Z.abs1(z2.Minus(r2, s))){ kappa.Times(sf, r1); } else{ kappa.Times(sf, r2); } // Perform the QR step. p.Minus(T.get(il,il), kappa); q.Eq(T.get(il+1,il)); Rot.genc(p.re, p.im, q.re, q.im, P); for (i=il; i