From f84bd3e7b1b669c9ad1469dbdd2929531db6645f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 6 Jul 2009 15:01:30 +0200 Subject: include the fixes of the third edition --- Eigen/src/SVD/SVD.h | 129 +++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 63 deletions(-) (limited to 'Eigen/src') diff --git a/Eigen/src/SVD/SVD.h b/Eigen/src/SVD/SVD.h index 71f6763a8..f27b7e66d 100644 --- a/Eigen/src/SVD/SVD.h +++ b/Eigen/src/SVD/SVD.h @@ -111,7 +111,7 @@ template class SVD protected: // Computes (a^2 + b^2)^(1/2) without destructive underflow or overflow. - inline static Scalar pythagora(Scalar a, Scalar b) + inline static Scalar pythag(Scalar a, Scalar b) { Scalar abs_a = ei_abs(a); Scalar abs_b = ei_abs(b); @@ -138,14 +138,13 @@ template class SVD /** Computes / recomputes the SVD decomposition A = U S V^* of \a matrix * - * \note this code has been adapted from Numerical Recipes, second edition. + * \note this code has been adapted from Numerical Recipes, third edition. */ template void SVD::compute(const MatrixType& matrix) { const int m = matrix.rows(); const int n = matrix.cols(); - const int nu = std::min(m,n); m_matU.resize(m, m); m_matU.setZero(); @@ -158,22 +157,24 @@ void SVD::compute(const MatrixType& matrix) MatrixType A = matrix; SingularValuesType& W = m_sigma; - int flag,i,its,j,jj,k,l,nm; + bool flag; + int i,its,j,jj,k,l,nm; Scalar anorm, c, f, g, h, s, scale, x, y, z; bool convergence = true; + Scalar eps = precision(); Matrix rv1(n); g = scale = anorm = 0; // Householder reduction to bidiagonal form. for (i=0; i::compute(const MatrixType& matrix) g = -sign( ei_sqrt(s), f ); h = f*g - s; A(i, i)=f-g; - for (j=l; j::compute(const MatrixType& matrix) A.col(i).end(m-i) *= scale; } } - W[i] = scale *g; + W[i] = scale * g; g = s = scale = 0.0; - if (i < m && i != (n-1)) + if (i+1 <= m && i+1 != n) { - scale = A.row(i).end(n-l).cwise().abs().sum(); - if (scale) + scale = A.row(i).end(n-l+1).cwise().abs().sum(); + if (scale != Scalar(0)) { - for (k=l; k=0; i--) + for (i=n-1; i>=0; i--) { //Accumulation of right-hand transformations. - if (i < (n-1)) + if (i < n-1) { - if (g) + if (g != Scalar(0.0)) { - for (j=l; j::compute(const MatrixType& matrix) { l = i+1; g = W[i]; - for (j=l; j0) + A.row(i).end(n-l).setZero(); + if (g != Scalar(0.0)) { - g = (Scalar)1.0/g; + g = Scalar(1.0)/g; for (j=l; j=0; k--) + for (k=n-1; k>=0; k--) { - for (its=1; its<=max_iters; its++) + for (its=0; its=0; l--) { // Test for splitting. - nm=l-1; + nm = l-1; // Note that rv1[1] is always zero. - if ((double)(ei_abs(rv1[l])+anorm) == anorm) + //if ((double)(ei_abs(rv1[l])+anorm) == anorm) + if (l==0 || ei_abs(rv1[l]) <= eps*anorm) { - flag=0; + flag = false; break; } - if ((double)(ei_abs(W[nm])+anorm) == anorm) + //if ((double)(ei_abs(W[nm])+anorm) == anorm) + if (ei_abs(W[nm]) <= eps*anorm) break; } if (flag) { - c=0.0; //Cancellation of rv1[l], if l > 1. - s=1.0; - for (i=l ;i<=k; i++) + c = 0.0; //Cancellation of rv1[l], if l > 0. + s = 1.0; + for (i=l ;i::compute(const MatrixType& matrix) } break; } - if (its == max_iters) + if (its+1 == max_iters) { convergence = false; } @@ -329,19 +332,19 @@ void SVD::compute(const MatrixType& matrix) y = W[nm]; g = rv1[nm]; h = rv1[k]; - f = ((y-z)*(y+z) + (g-h)*(g+h))/((Scalar)2.0*h*y); - g = pythagora(f,1.0); + f = ((y-z)*(y+z) + (g-h)*(g+h))/(Scalar(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; //Next QR transformation: - for (j=l; j<= nm;j++) + for (j=l; j<=nm; j++) { i = j+1; g = rv1[i]; y = W[i]; h = s*g; g = c*g; - z = pythagora(f,h); + z = pythag(f,h); rv1[j] = z; c = f/z; s = h/z; @@ -351,15 +354,15 @@ void SVD::compute(const MatrixType& matrix) y *= c; for (jj=0; jj::compute(const MatrixType& matrix) x = c*y - s*g; for (jj=0; jj