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= n"); } */ int nu = Math.min(m,n); s = new double [Math.min(m+1,n)]; U = new double [m][nu]; V = new double [n][n]; double[] e = new double [n]; double[] work = new double [m]; boolean wantu = true; boolean wantv = true; // Reduce A to bidiagonal form, storing the diagonal elements // in s and the super-diagonal elements in e. int nct = Math.min(m-1,n); int nrt = Math.max(0,Math.min(n-2,m)); for(k=0; k=0; k--){ if(s[k] != 0.0) { for(j=k+1; j=0; k--){ if((k < nrt) & (e[k] != 0.0)) for(j=k+1; j 0){ int kase; // Here is where a test for too many iterations would go. // // This section of the program inspects for // negligible elements in the s and e arrays. On // completion the variables kase and k are set as follows. // kase = 1 if s(p) and e[k-1] are negligible and k

=-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= s[k+1]) break; double t = s[k]; s[k] = s[k+1]; s[k+1] = t; if(wantv && (k < n-1)){ for(i=0; i tol) r++; return r; } }