package Jampack; /** Zsvd implements the singular value decomposion of a Zmat. Specifically if X is an mxn matrix with m>=n there are unitary matrices U and V such that
*     U^H*X*V = | S |
*               | 0 |
where S = diag(s1,...,sm) with
*     s1 >= s2 >= ... >= sn >=0.
If m<n the decomposition has the form
*     U^H*X*V = | S  0 |,
where S is diagonal of order m. The diagonals of S are the singular values of A. The columns of U are the left singular vectors of A and the columns of V are the right singular vectors. @version Pre-alpha @author G. W. Stewart */ public class Zsvd{ /** Limits the number of iterations in the SVD algorithm */ public static int MAXITER = 30; /** The matrix of left singular vectors */ public Zmat U; /** The matrix of right singular vectore */ public Zmat V; /** The diagonal matrix of singular values */ public Zdiagmat S; /** Computes the SVD of a Zmat XX. Throws a JampackException if the maximum number of iterations is exceeded. @param XX A Zmat @return The Zsvd of XX @exception JampackException Thrown if maximimum number of iterations is exceeded.
Passed from below. */ public Zsvd(Zmat XX) throws JampackException{ int i, il, iu, iter, j, k, kk, m, mc; double as, at, au, axkk, axkk1, dmax, dmin, ds, ea, es, shift, ss, t, tre; Z xkk, xkk1, xk1k1, ukj, vik1; Rot P = new Rot(); /* Initialization */ Z scale = new Z(); Z zr = new Z(); Zmat X = new Zmat(XX); Z1 h; Z1 temp = new Z1(Math.max(X.nr,X.nc)); mc = Math.min(X.nr, X.nc); double d[] = new double[mc]; double e[] = new double[mc]; S = new Zdiagmat(mc); U = Eye.o(X.nr); V = Eye.o(X.nc); m = Math.min(X.rx, X.cx); /* Reduction to Bidiagonal form. */ for (k=X.bx; k<=m; k++){ h = House.genc(X, k, X.rx, k); House.ua(h, X, k, X.rx, k+1, X.cx, temp); House.au(U, h, U.bx, U.rx, k, U.cx, temp); if (k != X.cx){ h = House.genr(X, k, k+1, X.cx); House.au(X, h, k+1, X.rx, k+1, X.cx, temp); House.au(V, h, V.bx, V.rx, k+1, V.cx, temp); } } /* Scale the bidiagonal matrix so that its elements are real. */ for (k=X.bx; k<=m; k++){ kk = k-X.bx; xkk = X.get(k,k); axkk = Z.abs(xkk); X.put(k, k, new Z(axkk)); d[kk] = axkk; scale.Div(scale.Conj(xkk), axkk); if (k=0; k--){ Rot.genr(d[k], t, P); d[k] = P.zr; if (k != 0){ t = P.sr*e[k-1]; e[k-1] = P.c*e[k-1]; } Rot.ap(V, P, V.bx, V.rx, k+V.bx, X.rx+1); Rot.ap(X, P, X.bx, X.rx, k+X.bx, X.rx+1); } } /* Caculate the singular values of the bidiagonal matrix. */ iu = m; iter = 0; while (true){ /* These two loops determine the rows (il to iu) to iterate on. */ while (iu > 0){ if (Math.abs(e[iu-1]) > 1.0e-16*(Math.abs(d[iu]) + Math.abs(d[iu-1]))) break; e[iu-1] = 0.; iter = 0; iu = iu - 1; } iter = iter+1; if (iter > MAXITER){ throw new JampackException ("Maximum number of iterations exceeded."); } if (iu == 0) break; il = iu-1; while(il > 0){ if(Math.abs(e[il-1]) <= 1.0e-16*(Math.abs(d[il]) + Math.abs(d[il-1]))) break; il = il-1; } if (il != 0){ e[il-1] = 0.; } /* Compute the shift (formulas adapted from LAPACK). */ dmax = Math.max(Math.abs(d[iu]), Math.abs(d[iu-1])); dmin = Math.min(Math.abs(d[iu]), Math.abs(d[iu-1])); ea = Math.abs(e[iu-1]); if (dmin == 0.){ shift = 0.; } else if(ea < dmax){ as = 1. + dmin/dmax; at = (dmax-dmin)/dmax; au = ea/dmax; au = au*au; shift =dmin*(2./(Math.sqrt(as*as+au) + Math.sqrt(at*at+au))); } else{ au = dmax/ea; if (au == 0.){ shift = (dmin*dmax)/ea; } else{ as = 1. + dmin/dmax; at = (dmax-dmin)/dmax; t = 1./(Math.sqrt(1.+(as*au)*(as*au))+ Math.sqrt(1.+(at*au)*(at*au))); shift = (t*dmin)*au; } } /* Perform the implicitly shifted QR step. */ t = Math.max(Math.max(Math.abs(d[il]),Math.abs(e[il])), shift); ds = d[il]/t; es=e[il]/t; ss = shift/t; Rot.genr((ds-ss)*(ds+ss), ds*es, P); for (i=il; i=0; k--){ if (d[k] < 0){ d[k] = -d[k]; for (i=0; i