The previous post was a discussion on employing Householder transformations to perform a QR decomposition. This post will be short. I've had this code lying around for a while now and thought I would make it available. The process of bidiagonalization using Householder transformations amounts to nothing more than alternating by left and right transformations.
The cMatrix::householderBidiagonalization()
method:
void cMatrix::householderBidiagonalization(cMatrix& Q, cMatrix& R, cMatrix& S) { double mag, alpha; cMatrix u(m, 1), v(m, 1), u_(n, 1), v_(n, 1); cMatrix P(m, m), I(m, m), P_(n, n), I_(n, n); Q = cMatrix(m, m); R = *this; S = cMatrix(n, n); for (int i = 0; i < n; i++) { u.zero(); v.zero(); mag = 0.0; for (int j = i; j < m; j++) { u.A[j] = R.A[j * n + i]; mag += u.A[j] * u.A[j]; } mag = sqrt(mag); alpha = u.A[i] < 0 ? mag : -mag; mag = 0.0; for (int j = i; j < m; j++) { v.A[j] = j == i ? u.A[j] + alpha : u.A[j]; mag += v.A[j] * v.A[j]; } mag = sqrt(mag); if (mag > 0.0000000001) { for (int j = i; j < m; j++) v.A[j] /= mag; P = I - (v * v.transpose()) * 2.0; R = P * R; Q = Q * P; } ///////////////////////// u_.zero(); v_.zero(); mag = 0.0; for (int j = i + 1; j < n; j++) { u_.A[j] = R.A[i * n + j]; mag += u_.A[j] * u_.A[j]; } mag = sqrt(mag); alpha = u_.A[i + 1] < 0 ? mag : -mag; mag = 0.0; for (int j = i + 1; j < n; j++) { v_.A[j] = j == i + 1 ? u_.A[j] + alpha : u_.A[j]; mag += v_.A[j] * v_.A[j]; } mag = sqrt(mag); if (mag > 0.0000000001) { for (int j = i + 1; j < n; j++) v_.A[j] /= mag; P_ = I_ - (v_ * v_.transpose()) * 2.0; R = R * P_; S = P_ * S; } } }
Download the source: qr_householder_bidiagonalization.cc.bz2