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