Blender  V2.59
svd.h
Go to the documentation of this file.
00001 
00005 #ifndef SVD_H
00006 
00007 #define SVD_H
00008 
00009 // Compute the Single Value Decomposition of an arbitrary matrix A
00010 // That is compute the 3 matrices U,W,V with U column orthogonal (m,n) 
00011 // ,W a diagonal matrix and V an orthogonal square matrix s.t. 
00012 // A = U.W.Vt. From this decomposition it is trivial to compute the 
00013 // inverse of A as Ainv = V.Winv.tranpose(U).
00014 //
00015 // s = diagonal elements of W
00016 // work1 = workspace, length must be A.num_rows
00017 // work2 = workspace, length must be A.num_cols
00018 
00019 #include "tntmath.h"
00020 
00021 #define SVD_MAX_ITER 200
00022 
00023 namespace TNT
00024 {
00025 
00026 template <class MaTRiX, class VecToR >
00027 void SVD(MaTRiX &A, MaTRiX &U, VecToR &s, MaTRiX &V, VecToR &work1, VecToR &work2, int maxiter=SVD_MAX_ITER) {
00028 
00029         int m = A.num_rows();
00030         int n = A.num_cols();
00031         int nu = min(m,n);
00032 
00033         VecToR& work = work1;
00034         VecToR& e = work2;
00035 
00036         U = 0;
00037         s = 0;
00038 
00039         int i=0, j=0, k=0;
00040 
00041         // Reduce A to bidiagonal form, storing the diagonal elements
00042         // in s and the super-diagonal elements in e.
00043 
00044         int nct = min(m-1,n);
00045         int nrt = max(0,min(n-2,m));
00046         for (k = 0; k < max(nct,nrt); k++) {
00047                 if (k < nct) {
00048 
00049                         // Compute the transformation for the k-th column and
00050                         // place the k-th diagonal in s[k].
00051                         // Compute 2-norm of k-th column without under/overflow.
00052                         s[k] = 0;
00053                         for (i = k; i < m; i++) {
00054                                 s[k] = hypot(s[k],A[i][k]);
00055                         }
00056                         if (s[k] != 0.0) {
00057                                 if (A[k][k] < 0.0) {
00058                                         s[k] = -s[k];
00059                                 }
00060                                 for (i = k; i < m; i++) {
00061                                         A[i][k] /= s[k];
00062                                 }
00063                                 A[k][k] += 1.0;
00064                         }
00065                         s[k] = -s[k];
00066                 }
00067                 for (j = k+1; j < n; j++) {
00068                         if ((k < nct) && (s[k] != 0.0))  {
00069 
00070                         // Apply the transformation.
00071 
00072                                 typename MaTRiX::value_type t = 0;
00073                                 for (i = k; i < m; i++) {
00074                                         t += A[i][k]*A[i][j];
00075                                 }
00076                                 t = -t/A[k][k];
00077                                 for (i = k; i < m; i++) {
00078                                         A[i][j] += t*A[i][k];
00079                                 }
00080                         }
00081 
00082                         // Place the k-th row of A into e for the
00083                         // subsequent calculation of the row transformation.
00084 
00085                         e[j] = A[k][j];
00086                 }
00087                 if (k < nct) {
00088 
00089                         // Place the transformation in U for subsequent back
00090                         // multiplication.
00091 
00092                         for (i = k; i < m; i++)
00093                                 U[i][k] = A[i][k];
00094                 }
00095                 if (k < nrt) {
00096 
00097                         // Compute the k-th row transformation and place the
00098                         // k-th super-diagonal in e[k].
00099                         // Compute 2-norm without under/overflow.
00100                         e[k] = 0;
00101                         for (i = k+1; i < n; i++) {
00102                                 e[k] = hypot(e[k],e[i]);
00103                         }
00104                         if (e[k] != 0.0) {
00105                                 if (e[k+1] < 0.0) {
00106                                         e[k] = -e[k];
00107                                 }
00108                                 for (i = k+1; i < n; i++) {
00109                                         e[i] /= e[k];
00110                                 }
00111                                 e[k+1] += 1.0;
00112                         }
00113                         e[k] = -e[k];
00114                         if ((k+1 < m) & (e[k] != 0.0)) {
00115 
00116                         // Apply the transformation.
00117 
00118                                 for (i = k+1; i < m; i++) {
00119                                         work[i] = 0.0;
00120                                 }
00121                                 for (j = k+1; j < n; j++) {
00122                                         for (i = k+1; i < m; i++) {
00123                                                 work[i] += e[j]*A[i][j];
00124                                         }
00125                                 }
00126                                 for (j = k+1; j < n; j++) {
00127                                         typename MaTRiX::value_type t = -e[j]/e[k+1];
00128                                         for (i = k+1; i < m; i++) {
00129                                                 A[i][j] += t*work[i];
00130                                         }
00131                                 }
00132                         }
00133 
00134                         // Place the transformation in V for subsequent
00135                         // back multiplication.
00136 
00137                         for (i = k+1; i < n; i++)
00138                                 V[i][k] = e[i];
00139                 }
00140         }
00141 
00142         // Set up the final bidiagonal matrix or order p.
00143 
00144         int p = min(n,m+1);
00145         if (nct < n) {
00146                 s[nct] = A[nct][nct];
00147         }
00148         if (m < p) {
00149                 s[p-1] = 0.0;
00150         }
00151         if (nrt+1 < p) {
00152                 e[nrt] = A[nrt][p-1];
00153         }
00154         e[p-1] = 0.0;
00155 
00156         // If required, generate U.
00157 
00158         for (j = nct; j < nu; j++) {
00159                 for (i = 0; i < m; i++) {
00160                         U[i][j] = 0.0;
00161                 }
00162                 U[j][j] = 1.0;
00163         }
00164         for (k = nct-1; k >= 0; k--) {
00165                 if (s[k] != 0.0) {
00166                         for (j = k+1; j < nu; j++) {
00167                                 typename MaTRiX::value_type t = 0;
00168                                 for (i = k; i < m; i++) {
00169                                         t += U[i][k]*U[i][j];
00170                                 }
00171                                 t = -t/U[k][k];
00172                                 for (i = k; i < m; i++) {
00173                                         U[i][j] += t*U[i][k];
00174                                 }
00175                         }
00176                         for (i = k; i < m; i++ ) {
00177                                 U[i][k] = -U[i][k];
00178                         }
00179                         U[k][k] = 1.0 + U[k][k];
00180                         for (i = 0; i < k-1; i++) {
00181                                 U[i][k] = 0.0;
00182                         }
00183                 } else {
00184                         for (i = 0; i < m; i++) {
00185                                 U[i][k] = 0.0;
00186                         }
00187                         U[k][k] = 1.0;
00188                 }
00189         }
00190 
00191         // If required, generate V.
00192 
00193         for (k = n-1; k >= 0; k--) {
00194                 if ((k < nrt) & (e[k] != 0.0)) {
00195                         for (j = k+1; j < nu; j++) {
00196                                 typename MaTRiX::value_type t = 0;
00197                                 for (i = k+1; i < n; i++) {
00198                                         t += V[i][k]*V[i][j];
00199                                 }
00200                                 t = -t/V[k+1][k];
00201                                 for (i = k+1; i < n; i++) {
00202                                         V[i][j] += t*V[i][k];
00203                                 }
00204                         }
00205                 }
00206                 for (i = 0; i < n; i++) {
00207                         V[i][k] = 0.0;
00208                 }
00209                 V[k][k] = 1.0;
00210         }
00211 
00212         // Main iteration loop for the singular values.
00213 
00214         int pp = p-1;
00215         int iter = 0;
00216         typename MaTRiX::value_type eps = pow(2.0,-52.0);
00217         while (p > 0) {
00218                 int kase=0;
00219                 k=0;
00220 
00221                 // Test for maximum iterations to avoid infinite loop
00222                 if(maxiter == 0)
00223                         break;
00224                 maxiter--;
00225 
00226                 // This section of the program inspects for
00227                 // negligible elements in the s and e arrays.  On
00228                 // completion the variables kase and k are set as follows.
00229 
00230                 // kase = 1       if s(p) and e[k-1] are negligible and k<p
00231                 // kase = 2       if s(k) is negligible and k<p
00232                 // kase = 3       if e[k-1] is negligible, k<p, and
00233                 //                                s(k), ..., s(p) are not negligible (qr step).
00234                 // kase = 4       if e(p-1) is negligible (convergence).
00235 
00236                 for (k = p-2; k >= -1; k--) {
00237                         if (k == -1) {
00238                                 break;
00239                         }
00240                         if (TNT::abs(e[k]) <= eps*(TNT::abs(s[k]) + TNT::abs(s[k+1]))) {
00241                                 e[k] = 0.0;
00242                                 break;
00243                         }
00244                 }
00245                 if (k == p-2) {
00246                         kase = 4;
00247                 } else {
00248                         int ks;
00249                         for (ks = p-1; ks >= k; ks--) {
00250                                 if (ks == k) {
00251                                         break;
00252                                 }
00253                                 typename MaTRiX::value_type t = (ks != p ? TNT::abs(e[ks]) : 0.) + 
00254                                                           (ks != k+1 ? TNT::abs(e[ks-1]) : 0.);
00255                                 if (TNT::abs(s[ks]) <= eps*t)  {
00256                                         s[ks] = 0.0;
00257                                         break;
00258                                 }
00259                         }
00260                         if (ks == k) {
00261                                 kase = 3;
00262                         } else if (ks == p-1) {
00263                                 kase = 1;
00264                         } else {
00265                                 kase = 2;
00266                                 k = ks;
00267                         }
00268                 }
00269                 k++;
00270 
00271                 // Perform the task indicated by kase.
00272 
00273                 switch (kase) {
00274 
00275                         // Deflate negligible s(p).
00276 
00277                         case 1: {
00278                                 typename MaTRiX::value_type f = e[p-2];
00279                                 e[p-2] = 0.0;
00280                                 for (j = p-2; j >= k; j--) {
00281                                         typename MaTRiX::value_type t = hypot(s[j],f);
00282                                         typename MaTRiX::value_type cs = s[j]/t;
00283                                         typename MaTRiX::value_type sn = f/t;
00284                                         s[j] = t;
00285                                         if (j != k) {
00286                                                 f = -sn*e[j-1];
00287                                                 e[j-1] = cs*e[j-1];
00288                                         }
00289 
00290                                         for (i = 0; i < n; i++) {
00291                                                 t = cs*V[i][j] + sn*V[i][p-1];
00292                                                 V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1];
00293                                                 V[i][j] = t;
00294                                         }
00295                                 }
00296                         }
00297                         break;
00298 
00299                         // Split at negligible s(k).
00300 
00301                         case 2: {
00302                                 typename MaTRiX::value_type f = e[k-1];
00303                                 e[k-1] = 0.0;
00304                                 for (j = k; j < p; j++) {
00305                                         typename MaTRiX::value_type t = hypot(s[j],f);
00306                                         typename MaTRiX::value_type cs = s[j]/t;
00307                                         typename MaTRiX::value_type sn = f/t;
00308                                         s[j] = t;
00309                                         f = -sn*e[j];
00310                                         e[j] = cs*e[j];
00311 
00312                                         for (i = 0; i < m; i++) {
00313                                                 t = cs*U[i][j] + sn*U[i][k-1];
00314                                                 U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1];
00315                                                 U[i][j] = t;
00316                                         }
00317                                 }
00318                         }
00319                         break;
00320 
00321                         // Perform one qr step.
00322 
00323                         case 3: {
00324 
00325                                 // Calculate the shift.
00326 
00327                                 typename MaTRiX::value_type scale = max(max(max(max(
00328                                                   TNT::abs(s[p-1]),TNT::abs(s[p-2])),TNT::abs(e[p-2])), 
00329                                                   TNT::abs(s[k])),TNT::abs(e[k]));
00330                                 typename MaTRiX::value_type sp = s[p-1]/scale;
00331                                 typename MaTRiX::value_type spm1 = s[p-2]/scale;
00332                                 typename MaTRiX::value_type epm1 = e[p-2]/scale;
00333                                 typename MaTRiX::value_type sk = s[k]/scale;
00334                                 typename MaTRiX::value_type ek = e[k]/scale;
00335                                 typename MaTRiX::value_type b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
00336                                 typename MaTRiX::value_type c = (sp*epm1)*(sp*epm1);
00337                                 typename MaTRiX::value_type shift = 0.0;
00338                                 if ((b != 0.0) || (c != 0.0)) {
00339                                         shift = sqrt(b*b + c);
00340                                         if (b < 0.0) {
00341                                                 shift = -shift;
00342                                         }
00343                                         shift = c/(b + shift);
00344                                 }
00345                                 typename MaTRiX::value_type f = (sk + sp)*(sk - sp) + shift;
00346                                 typename MaTRiX::value_type g = sk*ek;
00347 
00348                                 // Chase zeros.
00349 
00350                                 for (j = k; j < p-1; j++) {
00351                                         typename MaTRiX::value_type t = hypot(f,g);
00352                                         /* division by zero checks added to avoid NaN (brecht) */
00353                                         typename MaTRiX::value_type cs = (t == 0.0f)? 0.0f: f/t;
00354                                         typename MaTRiX::value_type sn = (t == 0.0f)? 0.0f: g/t;
00355                                         if (j != k) {
00356                                                 e[j-1] = t;
00357                                         }
00358                                         f = cs*s[j] + sn*e[j];
00359                                         e[j] = cs*e[j] - sn*s[j];
00360                                         g = sn*s[j+1];
00361                                         s[j+1] = cs*s[j+1];
00362 
00363                                         for (i = 0; i < n; i++) {
00364                                                 t = cs*V[i][j] + sn*V[i][j+1];
00365                                                 V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1];
00366                                                 V[i][j] = t;
00367                                         }
00368 
00369                                         t = hypot(f,g);
00370                                         /* division by zero checks added to avoid NaN (brecht) */
00371                                         cs = (t == 0.0f)? 0.0f: f/t;
00372                                         sn = (t == 0.0f)? 0.0f: g/t;
00373                                         s[j] = t;
00374                                         f = cs*e[j] + sn*s[j+1];
00375                                         s[j+1] = -sn*e[j] + cs*s[j+1];
00376                                         g = sn*e[j+1];
00377                                         e[j+1] = cs*e[j+1];
00378                                         if (j < m-1) {
00379                                                 for (i = 0; i < m; i++) {
00380                                                         t = cs*U[i][j] + sn*U[i][j+1];
00381                                                         U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1];
00382                                                         U[i][j] = t;
00383                                                 }
00384                                         }
00385                                 }
00386                                 e[p-2] = f;
00387                                 iter = iter + 1;
00388                         }
00389                         break;
00390 
00391                         // Convergence.
00392 
00393                         case 4: {
00394 
00395                                 // Make the singular values positive.
00396 
00397                                 if (s[k] <= 0.0) {
00398                                         s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
00399 
00400                                         for (i = 0; i <= pp; i++)
00401                                                 V[i][k] = -V[i][k];
00402                                 }
00403 
00404                                 // Order the singular values.
00405 
00406                                 while (k < pp) {
00407                                         if (s[k] >= s[k+1]) {
00408                                                 break;
00409                                         }
00410                                         typename MaTRiX::value_type t = s[k];
00411                                         s[k] = s[k+1];
00412                                         s[k+1] = t;
00413                                         if (k < n-1) {
00414                                                 for (i = 0; i < n; i++) {
00415                                                         t = V[i][k+1]; V[i][k+1] = V[i][k]; V[i][k] = t;
00416                                                 }
00417                                         }
00418                                         if (k < m-1) {
00419                                                 for (i = 0; i < m; i++) {
00420                                                         t = U[i][k+1]; U[i][k+1] = U[i][k]; U[i][k] = t;
00421                                                 }
00422                                         }
00423                                         k++;
00424                                 }
00425                                 iter = 0;
00426                                 p--;
00427                         }
00428                         break;
00429                 }
00430         }
00431 }
00432 
00433 }
00434 
00435 #endif
00436