/** * Returns the orthogonal V matrix. * * @param V If not null then the results will be stored here. Otherwise a new matrix will be created. * @return The extracted Q matrix. */ public virtual DMatrixRMaj getV(DMatrixRMaj V, bool transpose, bool compact) { V = handleV(V, transpose, compact, m, n, min); CommonOps_DDRM.setIdentity(V); // UBV.print(); // todo the very first multiplication can be avoided by setting to the rank1update output for (int j = min - 1; j >= 0; j--) { u[j + 1] = 1; for (int i = j + 2; i < n; i++) { u[i] = UBV.get(j, i); } if (transpose) { QrHelperFunctions_DDRM.rank1UpdateMultL(V, u, gammasV[j], j + 1, j + 1, n); } else { QrHelperFunctions_DDRM.rank1UpdateMultR(V, u, gammasV[j], j + 1, j + 1, n, this.b); } } return(V); }
/** * Returns the orthogonal U matrix. * * @param U If not null then the results will be stored here. Otherwise a new matrix will be created. * @return The extracted Q matrix. */ public virtual DMatrixRMaj getU(DMatrixRMaj U, bool transpose, bool compact) { U = handleU(U, transpose, compact, m, n, min); CommonOps_DDRM.setIdentity(U); for (int i = 0; i < m; i++) { u[i] = 0; } for (int j = min - 1; j >= 0; j--) { u[j] = 1; for (int i = j + 1; i < m; i++) { u[i] = UBV.get(i, j); } if (transpose) { QrHelperFunctions_DDRM.rank1UpdateMultL(U, u, gammasU[j], j, j, m); } else { QrHelperFunctions_DDRM.rank1UpdateMultR(U, u, gammasU[j], j, j, m, this.b); } } return(U); }
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; } }
/** * An orthogonal matrix that has the following property: T = Q<sup>T</sup>AQ * * @param Q If not null then the results will be stored here. Otherwise a new matrix will be created. * @return The extracted Q matrix. */ //@Override public DMatrixRMaj getQ(DMatrixRMaj Q, bool transposed) { Q = UtilDecompositons_DDRM.checkIdentity(Q, N, N); for (int i = 0; i < N; i++) { w[i] = 0; } if (transposed) { for (int j = N - 2; j >= 0; j--) { w[j + 1] = 1; for (int i = j + 2; i < N; i++) { w[i] = QT.data[j * N + i]; } QrHelperFunctions_DDRM.rank1UpdateMultL(Q, w, gammas[j + 1], j + 1, j + 1, N); } } else { for (int j = N - 2; j >= 0; j--) { w[j + 1] = 1; for (int i = j + 2; i < N; i++) { w[i] = QT.get(j, i); } QrHelperFunctions_DDRM.rank1UpdateMultR(Q, w, gammas[j + 1], j + 1, j + 1, N, b); } } return(Q); }
/** * Internal function for computing the decomposition. */ private bool _decompose() { double[] h = QH.data; for (int k = 0; k < N - 2; k++) { // 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 + 1; i < N; 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] = h[i * N + k]; val = Math.Abs(val); if (val > max) { max = val; } } if (max > 0) { // -------- set up the reflector Q_k double tau = 0; // normalize to reduce overflow/underflow // and compute tau for the reflector for (int i = k + 1; i < N; i++) { double val = u[i] /= max; tau += val * val; } tau = Math.Sqrt(tau); if (u[k + 1] < 0) { tau = -tau; } // write the reflector into the lower left column of the matrix double nu = u[k + 1] + tau; u[k + 1] = 1.0; for (int i = k + 2; i < N; i++) { h[i * N + k] = u[i] /= nu; } double gamma = nu / tau; gammas[k] = gamma; // ---------- multiply on the left by Q_k QrHelperFunctions_DDRM.rank1UpdateMultR(QH, u, gamma, k + 1, k + 1, N, b); // ---------- multiply on the right by Q_k QrHelperFunctions_DDRM.rank1UpdateMultL(QH, u, gamma, 0, k + 1, N); // since the first element in the householder vector is known to be 1 // store the full upper hessenberg h[(k + 1) * N + k] = -tau * max; } else { gammas[k] = 0; } } return(true); }
public bool bulgeSingleStepQn(int i, double a11, double a21, double threshold, bool set) { double max; if (normalize) { max = Math.Abs(a11); if (max < Math.Abs(a21)) { max = Math.Abs(a21); } // if( max <= Math.Abs(A.get(i,i))*UtilEjml.EPS ) { if (max <= threshold) { // Console.WriteLine("i = "+i); // A.print(); if (set) { A.set(i, i - 1, 0); A.set(i + 1, i - 1, 0); } return(false); } a11 /= max; a21 /= max; } else { max = 1; } // compute the reflector using the b's above double tau = Math.Sqrt(a11 * a11 + a21 * a21); if (a11 < 0) { tau = -tau; } double div = a11 + tau; u.set(i, 0, 1); u.set(i + 1, 0, a21 / div); gamma = div / tau; // compute A_1 = Q_1^T * A * Q_1 // apply Q*A - just do the 3 rows QrHelperFunctions_DDRM.rank1UpdateMultR(A, u.data, gamma, 0, i, i + 2, _temp.data); if (set) { A.set(i, i - 1, -max * tau); A.set(i + 1, i - 1, 0); } // apply A*Q - just the three things QrHelperFunctions_DDRM.rank1UpdateMultL(A, u.data, gamma, 0, i, i + 2); if (checkUncountable && MatrixFeatures_DDRM.hasUncountable(A)) { throw new InvalidOperationException("bad matrix"); } return(true); }