/** Singular Value Decomposition. U,S,V=svd(A);get...(): A=U*S*V^_T_

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, sigma[k] = S[k][k], are ordered so that sigma[0] >= sigma[1] >= ... >= sigma[n-1].

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.

(Adapted from JAMA, a Java Matrix Library, developed by jointly by the Mathworks and NIST; see http://math.nist.gov/javanumerics/jama). */ #ifdef JAMA_DYNAMIC int m, n; int nu,minm; #else #define nu MIN(m,n) #define minm MIN(m+1,n) #endif JamaArray2(Real,m,nu) U; JamaArray2(Real,n,n) V; JamaArray1(Real,minm) s; PUBLIC member(SVD) (const JamaArray2(Real,m,n) &Arg) { SVD0(Arg,1,1); } member(SVD) (const JamaArray2(Real,m,n) &Arg,int wantu,int wantv) { SVD0(Arg,wantu,wantv); } void member(SVD0) (const JamaArray2(Real,m,n) &Arg,int wantu,int wantv) { //allocation #ifdef JAMA_DYNAMIC m = Arg.NROWS(); n = Arg.NCOLS(); nu = MIN(m,n);//length of diagonal minm=MIN(m+1,n);//width of bidiagonal matrix. //s = JamaArray1(Real,minm)(minm); //U = JamaArray2(Real,m,nu)(m, nu);//, (0) //V = JamaArray2(Real,n,n)(n,n); RESIZE1(Real, s, minm); RESIZE2(Real, U, m ,nu); RESIZE2(Real, V, n, n); JamaArray1(Real,n) e(n); //PZ: e serves as storage for upper diagonal elements and also temporarily storage of last portion of rows. //PZ: thus, minm-1 elements would be not enough. //e[0]=D[0][1] JamaArray1(Real,m) work(m); JamaArray2(Real,m,n) A(COPY(Arg)); //end of allocation for (int i_=0;i_0) {A_:k=A_:k/norm(A_:k)+I_:k} // else $ s[k] = 0; for (i = k; i < m; i++) { $ s[k] = hypot_($ s[k],$ A[i][k]); } if ($ s[k] != 0.0) { if ($ A[k][k] < 0.0) {//PZ: two possible mirror vectors arose. one result -I_:k, other +I_:k after mirroring A_:k $ s[k] = -$ s[k]; //PZ: this chooses the longer one, to avoid numeric instability if A_:k is very near to I_:k } for (i = k; i < m; i++) { $ A[i][k] /= $ s[k]; } $ A[k][k] += 1.0;//PZ: A_:k contains the vector perpendicular to the desired mirroring } $ s[k] = -$ s[k];//PZ: Mirror(A_:k) original=s_k*I_:k. The sign depends on the choosen vector } for (j = k+1; j < n; j++) { if ((k < nct) && ($ s[k] != 0.0)) { // Apply the transformation. //PZ: mirroring to the plane perp. to A_:k Real t(0.0); for (i = k; i < m; i++) { t += $ A[i][k]*$ A[i][j]; }//PZ: t=A[K:end][k]^_T_*A[k:end][j] t = -t/$ A[k][k]; //PZ: t=-A[K:end][k]^_T_*A[k:end][j]/A[k][k] for (i = k; i < m; i++) { $ A[i][j] += t*$ A[i][k]; } //PZ: A[k:end][j]-=A[k:end][k]*(A[K:end][k]^_T_*A[k:end][j])/A[k][k] //PZ: A[k:end][j]=A[k:end][j]-A[k:end][k]*(A[K:end][k]^_T_*A[k:end][j])/A[k][k] //PZ: A_:j=(I -A_:k*A_:k^T/A_kk)*A_:j //PZ: since A_kk = 2*||A_:k||^2, thus the transformation is I-2*A_:k*A_:k^T/||A_:k||^2 and is orthogonal. } // Place the k-th row of A into e for the // subsequent calculation of the row transformation. $ e[j] = $ A[k][j]; } if (wantu & (k < nct)) { // Place the transformation in U for subsequent back // multiplication. for (i = k; i < m; i++) { $ U[i][k] = $ A[i][k];//PZ: the non-unit length normal vector of the mirroring plane, U_kk is twice the length squared } } if (k < nrt) { // Compute the k-th row transformation and place the // k-th super-diagonal in e[k]. // Compute 2-norm without under/overflow. $ e[k] = 0; for (i = k+1; i < n; i++) { $ e[k] = hypot_($ e[k],$ e[i]); } if ($ e[k] != 0.0) { if ($ e[k+1] < 0.0) {//PZ: Same formulation as for row transformations $ e[k] = -$ e[k]; } for (i = k+1; i < n; i++) { $ e[i] /= $ e[k]; } $ e[k+1] += 1.0; } $ e[k] = -$ e[k]; if ((k+1 < m) & ($ e[k] != 0.0)) { // Apply the transformation. for (i = k+1; i < m; i++) { $ work[i] = 0.0; } for (j = k+1; j < n; j++) { for (i = k+1; i < m; i++) { $ work[i] += $ e[j]*$ A[i][j]; } } for (j = k+1; j < n; j++) { Real t(-$ e[j]/$ e[k+1]); for (i = k+1; i < m; i++) { $ A[i][j] += t*$ work[i]; } } } if (wantv) { // Place the transformation in V for subsequent // back multiplication. for (i = k+1; i < n; i++) { $ V[i][k] = $ e[i];//PZ the non-uniform mirroring vector } } } } // Set up the final bidiagonal matrix or order p. int p = MIN(n,m+1); if (nct < n) { $ s[nct] = $ A[nct][nct]; } if (m < p) {//PZ: if(n>m && p==m+1) $ s[p-1] = 0.0; //PZ: s[m]=0.0 } if (nrt+1 < p) { $ e[nrt] = $ A[nrt][p-1]; } $ e[p-1] = 0.0; // If required, generate U. if (wantu) { //PZ: transform the collection of mirror-plane normal vectors into a single orthogonal transformation for (j = nct; j < nu; j++) { for (i = 0; i < m; i++) { $ U[i][j] = 0.0; } $ U[j][j] = 1.0; } for (k = nct-1; k >= 0; k--) { if ($ s[k] != 0.0) { for (j = k+1; j < nu; j++) { Real t(0.0); for (i = k; i < m; i++) { t += $ U[i][k]*$ U[i][j]; } t = -t/$ U[k][k]; for (i = k; i < m; i++) { $ U[i][j] += t*$ U[i][k]; } } for (i = k; i < m; i++ ) { $ U[i][k] = -$ U[i][k]; } $ U[k][k] = (Real) (1.0 + $ U[k][k] ); for (i = 0; i < k-1; i++) { $ U[i][k] = 0.0; } } else { //PZ: U_:k=I_:k for (i = 0; i < m; i++) { $ U[i][k] = 0.0; } $ U[k][k] = 1.0; } } } // If required, generate V. if (wantv) { //PZ: transform the collection of mirror-plane normal vectors into a single orthogonal transformation for (k = n-1; k >= 0; k--) {//PZ step back on each column if ((k < nrt) && ($ e[k] != 0.0)) { for (j = k+1; j < nu; j++) {//for all column to the right Real t(0.0); for (i = k+1; i < n; i++) { t += $ V[i][k]*$ V[i][j]; } //substract the kth column from all righter... t = t/$ V[k+1][k]; for (i = k+1; i < n; i++) { $ V[i][j] -= t*$ V[i][k]; } } } //PZ write the kth. unit vector for (i = 0; i < n; i++) { $ V[i][k] = 0.0; } $ V[k][k] = 1.0; } } // Main iteration loop for the singular values. //PZ: at this point, if wantu=1 and wantv=1, then Arg=U*D*V^T. //PZ: for all aplicable k, D[k][k]=s[k], D[k][k+1]=e[k] int pp = p-1; int iter = 0; Real eps = EPSILON(Real); while (p > 0) { int k=0; int kase=0; // 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. // action: // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) { if (k == -1) { break; } if (ABS($ e[k]) <= eps*(ABS($ s[k]) + 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; } Real t=(Real)( (ks != p ? ABS($ e[ks]) : 0.) + (ks != k+1 ? ABS($ e[ks-1]) : 0.)); if (ABS($ s[ks]) <= 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: { Real f($ e[p-2]); $ e[p-2] = 0.0; for (j = p-2; j >= k; j--) { Real t( hypot_($ s[j],f)); Real cs($ s[j]/t); Real 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 < n; i++) { t = cs*$ V[i][j] + sn*$ V[i][p-1]; $ V[i][p-1] = -sn*$ V[i][j] + cs*$ V[i][p-1]; $ V[i][j] = t; } } } } break; // Split at negligible s(k). case 2: { Real f($ e[k-1]); $ e[k-1] = 0.0; for (j = k; j < p; j++) { Real t(hypot_($ s[j],f)); Real cs( $ s[j]/t); Real sn(f/t); $ s[j] = t; f = -sn*$ e[j]; $ e[j] = cs*$ e[j]; if (wantu) { for (i = 0; i < m; i++) { t = cs*$ U[i][j] + sn*$ U[i][k-1]; $ U[i][k-1] = -sn*$ U[i][j] + cs*$ U[i][k-1]; $ U[i][j] = t; } } } } break; // Perform one qr step. case 3: { // Calculate the shift. Real scale = MAX(MAX(MAX(MAX( ABS($ s[p-1]),ABS($ s[p-2])),ABS($ e[p-2])), ABS($ s[k])),ABS($ e[k])); Real sp = $ s[p-1]/scale;//PZ: calculating 1/scale would not include numeric overflow....? Real spm1 = $ s[p-2]/scale; Real epm1 = $ e[p-2]/scale; Real sk = $ s[k]/scale; Real ek = $ e[k]/scale; Real b = (Real)(((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0); Real c = (sp*epm1)*(sp*epm1); Real shift = 0.0; if ((b != 0.0) || (c != 0.0)) { shift = sqrt(b*b + c); if (b < 0.0) { shift = -shift; } shift = c/(b + shift); } Real f = (sk + sp)*(sk - sp) + shift; Real g = sk*ek; // Chase zeros. for (j = k; j < p-1; j++) { Real t = hypot_(f,g); Real cs = f/t; Real sn = g/t; if (j != k) { $ e[j-1] = t; } f = cs*$ s[j] + sn*$ e[j]; $ e[j] = cs*$ e[j] - sn*$ s[j]; g = sn*$ s[j+1]; $ s[j+1] = cs*$ s[j+1]; if (wantv) { for (i = 0; i < n; i++) { t = cs*$ V[i][j] + sn*$ V[i][j+1]; $ V[i][j+1] = -sn*$ V[i][j] + cs*$ V[i][j+1]; $ V[i][j] = t; } } t = hypot_(f,g); cs = f/t; sn = g/t; $ s[j] = t; f = cs*$ e[j] + sn*$ s[j+1]; $ s[j+1] = -sn*$ e[j] + cs*$ s[j+1]; g = sn*$ e[j+1]; $ e[j+1] = cs*$ e[j+1]; if (wantu && (j < m-1)) { for (i = 0; i < m; i++) { t = cs*$ U[i][j] + sn*$ U[i][j+1]; $ U[i][j+1] = -sn*$ U[i][j] + cs*$ U[i][j+1]; $ U[i][j] = t; } } } $ e[p-2] = f; iter = iter + 1; } break; // Convergence. case 4: { // Make the singular values positive. if ($ s[k] <= 0.0) { $ s[k] = (Real)($ s[k] < 0.0 ? -$ s[k] : 0.0); if (wantv) { for (i = 0; i <= pp; i++) { $ V[i][k] = -$ V[i][k]; } } } // Order the singular values by bubble sort while (k < pp) { if ($ s[k] >= $ s[k+1]) { break;//nothing to do } //PZ exchange s[k <> k+1], U[:,k<>k+1], V[:,k<>k+1], Real t = $ s[k]; $ s[k] = $ s[k+1]; $ s[k+1] = t; if (wantv && (k < n-1)) { for (i = 0; i < n; i++) { t = $ V[i][k+1]; $ V[i][k+1] = $ V[i][k]; $ V[i][k] = t; } } if (wantu && (k < m-1)) { for (i = 0; i < m; i++) { t = $ U[i][k+1]; $ U[i][k+1] = $ U[i][k]; $ U[i][k] = t; } } k++; } iter = 0; p--; } break; } } } // void member(getU) (JamaArray2(Real,m,minm) &A) void member(getU) (JamaArray2(Real,m,nu) &A) //PZ { // int minm = MIN(m+1,n); // RESIZE2(Real,A,m,minm); RESIZE2(Real,A,m,nu);//PZ //#ifdef __cplusplus // A = JamaArray2(Real,m,minm)(m, minm); //#endif for (int i=0; in //need to calculate one null vector of U //return one normalized column of 1-U*U^T JamaArray2(Real,m,m) A; A=-U*(U^_T_); for(int i=0;imax_){ max_=s;maxi=i;maxj=j; } } } //normalize its row Real l=0.0; for(int j=0;j tol) { r++; } } return r; }