void SingularValueDecomposition<Real>::HouseholderQR ( const GMatrix<Real>& A, GMatrix<Real>& Q, GMatrix<Real>& R) { // The matrix R gets a copy of A, and is then overwritten during the // algorithm with the correct entries to be upper triangular. R = A; int numRows = R.GetNumRows(); int numCols = R.GetNumColumns(); assertion(numRows >= numCols, "Too many columns (use transpose)\n"); int row, col; GVector<Real> V(numRows); std::vector<GVector<Real> > VSave; for (col = 0; col < numCols; ++col) { // Create the Householder vector for the partial column of A. for (row = 0; row < col; ++row) { V[row] = (Real)0; } Real length = (Real)0; for (row = col; row < numRows; ++row) { V[row] = R[row][col]; length += V[row]*V[row]; } length = Math<Real>::Sqrt(length); Real beta = V[col] + Math<Real>::Sign(V[col])*length; if (beta != (Real)0) { Real invBeta = ((Real)1)/beta; for (int i = col + 1; i < numRows; ++i) { V[i] *= invBeta; } } V[col] = (Real)1; // Premultiply A by the V-reflection matrix. HouseholderPremultiply(V, R); // Save the Householder vectors. VSave.push_back(V); } // First, make Q the identity. Second, extract the Householder vectors // and premultiply by the V-reflections to build Q. memset(Q.GetElements(), 0, Q.GetNumElements()*sizeof(Real)); for (row = 0; row < numRows; ++row) { Q[row][row] = (Real)1; } for (col = numCols - 1; col >= 0; --col) { // Get the Householder vector. V = VSave[col]; // Premultiply Q by the V-reflection matrix. HouseholderPremultiply(V, Q); } }