package math.matrix; import java.io.Serializable; import math.Maths; /** Singular Value Decomposition. *
* For an m-by-n matrix A with m ≥ n, the singular value decomposition is * an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and * an n-by-n orthogonal matrix V so that A = U*S*V'. *
* The singular values, σk = Skk, are ordered so that * σ1 ≥ σ2 ≥ ... ≥ σn. *
* The singular value decompostion always exists, so the constructor will
* never fail. The matrix condition number and the effective numerical
* rank can be computed from this decomposition.
*/
public class SingularValueDecomposition implements Serializable {
/**
* UID
*/
private static final long serialVersionUID = -4816488865370991490L;
/**
* Array for internal storage of U.
* @serial internal storage of U.
*/
private double[][] U;
/**
* Array for internal storage of V.
* @serial internal storage of V.
*/
private double[][] V;
/**
* Array for internal storage of singular values.
* @serial internal storage of singular values.
*/
private double[] s;
/**
* Row dimensions.
* @serial row dimension.
*/
private int m;
/**
* Column dimensions.
* @serial column dimension.
*/
private int n;
/* ------------------------
Constructor
* ------------------------ */
/**
* Construct the singular value decomposition Structure to access U, S and V.
* @param Arg rectangular matrix
*/
public SingularValueDecomposition(Matrix Arg){
int i, j, k;
// Derived from LINPACK code.
// Initialize.
double[][] A = Arg.getCopy();
m = Arg.getM();
n = Arg.getN();
/* TODO: Apparently the failing cases are only a proper subset of (m =-1; k--){
if(k == -1) break;
if(Math.abs(e[k]) <=
tiny + eps*(Math.abs(s[k]) + Math.abs(s[k+1]))){
e[k] = 0.0;
break;
}
}
if(k == p-2)
kase = 4;
else {
int ks;
for(ks=p-1; ks>=k; ks--){
if (ks == k) break;
double t = (ks != p ? Math.abs(e[ks]) : 0.) +
(ks != k+1 ? Math.abs(e[ks-1]) : 0.);
if(Math.abs(s[ks]) <= tiny + eps*t){
s[ks] = 0.0;
break;
}
}
if(ks == k)
kase = 3;
else if(ks == p-1)
kase = 1;
else {
kase = 2;
k = ks;
}
}
k++;
// Perform the task indicated by kase.
switch (kase) {
// Deflate negligible s(p).
case 1: {
double f = e[p-2];
e[p-2] = 0.0;
for(j=p-2; j>=k; j--){
double t = Maths.hypot(s[j],f);
double cs = s[j]/t;
double sn = f/t;
s[j] = t;
if(j != k){
f = -sn*e[j-1];
e[j-1] = cs*e[j-1];
}
if(wantv)
for(i=0; i