/** * Computes and performs the similar a transform for submatrix k. */ private void similarTransform(int k) { double[] t = QT.data; // find the largest value in this column // this is used to normalize the column and mitigate overflow/underflow double max = 0; int rowU = (k - 1) * N; for (int i = k; i < N; i++) { double val = Math.Abs(t[rowU + i]); if (val > max) { max = val; } } if (max > 0) { // -------- set up the reflector Q_k double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k, N, t, rowU, max); // write the reflector into the lower left column of the matrix double nu = t[rowU + k] + tau; QrHelperFunctions_DDRM.divideElements(k + 1, N, t, rowU, nu); t[rowU + k] = 1.0; double gamma = nu / tau; gammas[k] = gamma; // ---------- Specialized householder that takes advantage of the symmetry householderSymmetric(k, gamma); // since the first element in the householder vector is known to be 1 // store the full upper hessenberg t[rowU + k] = -tau * max; } else { gammas[k] = 0; } }
protected void computeU(int k) { double[] b = UBV.data; // find the largest value in this column // this is used to normalize the column and mitigate overflow/underflow double max = 0; for (int i = k; i < m; i++) { // copy the householder vector to vector outside of the matrix to reduce caching issues // big improvement on larger matrices and a relatively small performance hit on small matrices. double val = u[i] = b[i * n + k]; val = Math.Abs(val); if (val > max) { max = val; } } if (max > 0) { // -------- set up the reflector Q_k double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k, m, u, max); // write the reflector into the lower left column of the matrix // while dividing u by nu double nu = u[k] + tau; QrHelperFunctions_DDRM.divideElements_Bcol(k + 1, m, n, u, b, k, nu); u[k] = 1.0; double gamma = nu / tau; gammasU[k] = gamma; // ---------- multiply on the left by Q_k QrHelperFunctions_DDRM.rank1UpdateMultR(UBV, u, gamma, k + 1, k, m, this.b); b[k * n + k] = -tau * max; } else { gammasU[k] = 0; } }
protected void computeV(int k) { double[] b = UBV.data; int row = k * n; // find the largest value in this column // this is used to normalize the column and mitigate overflow/underflow double max = QrHelperFunctions_DDRM.findMax(b, row + k + 1, n - k - 1); if (max > 0) { // -------- set up the reflector Q_k double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k + 1, n, b, row, max); // write the reflector into the lower left column of the matrix double nu = b[row + k + 1] + tau; QrHelperFunctions_DDRM.divideElements_Brow(k + 2, n, u, b, row, nu); u[k + 1] = 1.0; double gamma = nu / tau; gammasV[k] = gamma; // writing to u could be avoided by working directly with b. // requires writing a custom rank1Update function // ---------- multiply on the left by Q_k QrHelperFunctions_DDRM.rank1UpdateMultL(UBV, u, gamma, k + 1, k + 1, n); b[row + k + 1] = -tau * max; } else { gammasV[k] = 0; } }