void SvdCmp(double **a, int m, int n, double w[], double **v) { // SVD Composition int flag,i,its,j,jj,k,l,nm; double anorm,c,f,g,h,s,scale,x,y,z,*rv1; rv1=dVector(1,n); g=scale=anorm=0.0; for (i=1;i<=n;i++) { l=i+1; rv1[i]=scale*g; g=s=scale=0.0; if (i <= m) { for (k=i;k<=m;k++) scale += fabs(a[k][i]); if (scale) { for (k=i;k<=m;k++) { a[k][i] /= scale; s += a[k][i]*a[k][i]; } f=a[i][i]; g = -SIGN(sqrt(s),f); h=f*g-s; a[i][i]=f-g; for (j=l;j<=n;j++) { for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j]; f=s/h; for (k=i;k<=m;k++) a[k][j] += f*a[k][i]; } for (k=i;k<=m;k++) a[k][i] *= scale; } } w[i]=scale *g; g=s=scale=0.0; if (i <= m && i != n) { for (k=l;k<=n;k++) scale += fabs(a[i][k]); if (scale) { for (k=l;k<=n;k++) { a[i][k] /= scale; s += a[i][k]*a[i][k]; } f=a[i][l]; g = -SIGN(sqrt(s),f); h=f*g-s; a[i][l]=f-g; for (k=l;k<=n;k++) rv1[k]=a[i][k]/h; for (j=l;j<=m;j++) { for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k]; for (k=l;k<=n;k++) a[j][k] += s*rv1[k]; } for (k=l;k<=n;k++) a[i][k] *= scale; } } anorm=__max(anorm,(fabs(w[i])+fabs(rv1[i]))); } for (i=n;i>=1;i--) { if (i < n) { if (g) { for (j=l;j<=n;j++) v[j][i]=(a[i][j]/a[i][l])/g; for (j=l;j<=n;j++) { for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j]; for (k=l;k<=n;k++) v[k][j] += s*v[k][i]; } } for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0; } v[i][i]=1.0; g=rv1[i]; l=i; } for (i=__min(m,n);i>=1;i--) { l=i+1; g=w[i]; for (j=l;j<=n;j++) a[i][j]=0.0; if (g) { g=1.0/g; for (j=l;j<=n;j++) { for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j]; f=(s/a[i][i])*g; for (k=i;k<=m;k++) a[k][j] += f*a[k][i]; } for (j=i;j<=m;j++) a[j][i] *= g; } else for (j=i;j<=m;j++) a[j][i]=0.0; ++a[i][i]; } for (k=n;k>=1;k--) { for (its=1;its<=100;its++) { flag=1; for (l=k;l>=1;l--) { nm=l-1; if ((double)(fabs(rv1[l])+anorm) == anorm) { flag=0; break; } if ((double)(fabs(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 ((double)(fabs(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=1;j<=m;j++) { y=a[j][nm]; z=a[j][i]; a[j][nm]=y*c+z*s; a[j][i]=z*c-y*s; } } } z=w[k]; if (l == k) { if (z < 0.0) { w[k] = -z; for (j=1;j<=n;j++) v[j][k] = -v[j][k]; } break; } if (its == 100) nrerror("no convergence in 30 svdcmp iterations"); x=w[l]; nm=k-1; y=w[nm]; g=rv1[nm]; h=rv1[k]; f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y); g=Pythag(f,1.0); f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x; c=s=1.0; for (j=l;j<=nm;j++) { i=j+1; g=rv1[i]; y=w[i]; h=s*g; g=c*g; z=Pythag(f,h); rv1[j]=z; c=f/z; s=h/z; f=x*c+g*s; g = g*c-x*s; h=y*s; y *= c; for (jj=1;jj<=n;jj++) { x=v[jj][j]; z=v[jj][i]; v[jj][j]=x*c+z*s; v[jj][i]=z*c-x*s; } z=Pythag(f,h); w[j]=z; if (z) { z=1.0/z; c=f*z; s=h*z; } f=c*g+s*y; x=c*y-s*g; for (jj=1;jj<=m;jj++) { y=a[jj][j]; z=a[jj][i]; a[jj][j]=y*c+z*s; a[jj][i]=z*c-y*s; } } rv1[l]=0.0; rv1[k]=f; w[k]=x; } } Free_dVector(rv1,1,n); }
//========================================================================== // Class: Matrix // Function: DiagonalizeBidiagonalForm // // Description: Part of SVD algorithm. "Diagonalizes the bidiagonal form." // // Input Arguments: // U = Matrix& // V = Matrix& // W = Matrix& // rv1 = double* // anorm = const double& // // Output Arguments: // None // // Return Value: // bool, false if iteration limit was reached, true otherwise // //========================================================================== bool Matrix::DiagonalizeBidiagonalForm(Matrix &U, Matrix &V, Matrix &W, double *rv1, const double &anorm) const { int i, j, its, jj, k, l(0), nm(0); double c, f, g, h, s, x, y, z; bool finished; double eps = 1.0e-6; int its_limit = 30; for (k = V.rows - 1; k >= 0; k--) { for (its = 0; its < its_limit; its++) { finished = false; for (l = k; l >= 0; l--) { nm = l - 1; if (l == 0 || fabs(rv1[l]) <= eps * anorm) { finished = true; break; } if (fabs(W.elements[nm][nm]) <= eps * anorm) break; } if (!finished) { c = 0.0; s = 1.0; for (i = l; i <= k; i++) { f = s * rv1[i]; rv1[i] = c * rv1[i]; if (fabs(f) <= eps * anorm) break; g = W.elements[i][i]; h = Pythag(f, g); W.elements[i][i] = h; h = 1.0 / h; c = g * h; s = -f * h; for (j = 0; j < (int)U.rows; j++) { y = U.elements[j][nm]; z = U.elements[j][i]; U.elements[j][nm] = y * c + z * s; U.elements[j][i] = z * c - y * s; } } } z = W.elements[k][k]; if (l == k) { if (z < 0.0) { W.elements[k][k] = -z; for (j = 0; j < (int)V.rows; j++) V.elements[j][k] = -V.elements[j][k]; } break; } if (its == its_limit - 1)// Reached iteration limit return false; x = W.elements[l][l]; nm = k - 1; y = W.elements[nm][nm]; g = rv1[nm]; h = rv1[k]; f = ((y-z) * (y+z) + (g-h) * (g+h)) / (2.0 * h * y); g = Pythag(f, 1.0); if (f >= 0.0) f = ((x-z) * (x+z) + h * ((y / (f + fabs(g))) - h)) / x; else f = ((x-z) * (x+z) + h * ((y / (f - fabs(g))) - h)) / x; c = 1.0; s = 1.0; for (j = l; j <= nm; j++) { i = j + 1; g = rv1[i]; y = W.elements[i][i]; h = s * g; g = c * g; z = Pythag(f,h); rv1[j] = z; c = f / z; s = h / z; f = x * c + g * s; g = g * c - x * s; h = y * s; y *= c; for (jj = 0; jj < (int)V.rows; jj++) { x = V.elements[jj][j]; z = V.elements[jj][i]; V.elements[jj][j] = x * c + z * s; V.elements[jj][i] = z * c - x * s; } z = Pythag(f, h); W.elements[j][j] = z; if (z != 0.0) { z = 1.0 / z; c = f * z; s = h * z; } f = c * g + s * y; x = c * y - s * g; for (jj = 0; jj < (int)U.rows; jj++) { y = U.elements[jj][j]; z = U.elements[jj][i]; U.elements[jj][j] = y * c + z * s; U.elements[jj][i] = z * c - y * s; } } rv1[l] = 0.0; rv1[k] = f; W.elements[k][k] = x; } } return true; }