// SVD in java // translated from NR svdcmp.c, this has worked on several examples, // but check the results before trusting it completely // // zlib - this just contains an assert routine, you can comment it out. package ZS; import zlib.*; /**************** results from matlab M = [1.0, 1.0, 1.0, 1.0, 1.0; 0.0, 0.7578582801241234, 0.8705505614977934, 0.9440875104854797, 1.0; 0.0, 0.5743491727526943, 0.7578582801241234, 0.8913012274546708, 1.0; 0.0, 0.4352752672614163, 0.6597539444834084, 0.841466353313137, 1.0; 0.0, 0.3298769722417042, 0.5743491727526943, 0.7944178780622027, 1.0; 0.0, 0.25, 0.5, 0.75, 1.0 ] [U,D,V] = svd(M); D D = 4.0143 0 0 0 0 0 0.9803 0 0 0 0 0 0.3522 0 0 0 0 0 0.0209 0 0 0 0 0 0.0004 0 0 0 0 0 >> V V = 0.1290 -0.8538 0.5019 -0.0503 0.0022 0.3605 -0.3537 -0.6377 0.5576 -0.1651 0.4543 -0.0929 -0.3332 -0.5544 0.6055 0.5325 0.1348 0.0544 -0.4113 -0.7254 0.6029 0.3452 0.4769 0.4583 0.2827 ---------------- results from java version: D= [ 4.014 0.980 0.352 0.021 0.000 ] V= [ -0.129 0.854 -0.502 0.050 0.002 ] [ -0.360 0.354 0.638 -0.558 -0.165 ] [ -0.454 0.093 0.333 0.554 0.606 ] [ -0.533 -0.135 -0.054 0.411 -0.725 ] [ -0.603 -0.345 -0.477 -0.458 0.283 ] ****************/ /** */ public final class SVD_NR { /** * returns U in a. normaly U is nr*nr, * but if nr>nc only the first nc columns are returned * (nice, saves memory). * The columns of U have arbitrary sign, * also the columns corresponding to near-zero singular values * can vary wildly from other implementations. */ public static void svd(double[][] a,double[] w,double[][] v) { int i,its,j,jj,k,l=0,nm=0; boolean flag; int m = a.length; int n = a[0].length; double c,f,h,s,x,y,z; double anorm = 0., g = 0., scale=0. ; zliberror._assert(m>=n) ; double[] rv1 = new double[n]; System.out.println("SVD beware results may not be sorted!"); for (i = 0; i=0; --i) { if (i=1;i--) { // ! //for (i = n-1; i>=0; --i) { for (i = Math.min(m-1,n-1); i>=0; --i) { l = i+1; g = w[i]; if (i=0; --k) { for (its = 1; its<=30; ++its) { flag = true; for (l = k; l>=0; --l) { nm = l-1; if ((abs(rv1[l])+anorm) == anorm) { flag = false; break ; } if ((abs(w[nm])+anorm) == anorm) break; } if (flag) { c = 0.0; s = 1.0; for (i = l; i<=k; i++) { // f = s*rv1[i]; rv1[i] = c*rv1[i]; if ((abs(f)+anorm)==anorm) break; g = w[i]; h = pythag(f,g) ; w[i] = h; h = 1.0/h; c = g*h; s = -f*h; for (j = 0; j= 0. ? abs(a) : -abs(a)); } //---------------------------------------------------------------- // test it public static void main(String[] cmdline) { int nr = 6; int nc = 5 ; //int nr = 300; int nc = 300; //int nr = 600; int nc = 600; double[][] M = new double[nr][nc] ; for( int r = 0; r < nr; r++ ) { float p = (float)r / (nr-1); for( int c = 0; c < nc; c++ ) { float frac = (float)c / (nc-1); M[r][c] = Math.pow(frac,p); } } if (nr < 10) matrix.print("M=",M); double[] w = new double[nc]; double[][] V = new double[nc][nc]; svd(M, w, V); matrix.print("D=",w); if (nr < 10) matrix.print("V=",V); System.exit(0); } //main } //SVD_NR