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; } }
private void performDecomposition(DMatrixSparseCSC A) { int[] w = gwork.data; int[] permCol = applyReduce.getArrayQ(); int[] parent = structure.getParent(); int[] leftmost = structure.getLeftMost(); // permutation that was done to ensure all rows have non-zero elements int[] pinv_structure = structure.getPinv(); int s = m2; // clear mark nodes. See addRowsInAInToC //Arrays.fill(w, 0, m2, -1); for (var i = 0; i < m2; i++) { w[i] = -1; } //Arrays.fill(x, 0, m2, 0); Array.Clear(x, 0, m2); // the counts from structure are actually an upper limit. the actual counts can be lower R.nz_length = 0; V.nz_length = 0; // compute V and R for (int k = 0; k < n; k++) { R.col_idx[k] = R.nz_length; int p1 = V.col_idx[k] = V.nz_length; w[k] = k; V.nz_rows[V.nz_length++] = k; // Add V(k,k) to V's pattern int top = n; int col = permCol != null ? permCol[k] : k; int idx0 = A.col_idx[col]; int idx1 = A.col_idx[col + 1]; for (int p = idx0; p < idx1; p++) { int i = leftmost[A.nz_rows[p]]; int len; for (len = 0; w[i] != k; i = parent[i]) { w[s + len++] = i; w[i] = k; } while (len > 0) { w[s + --top] = w[s + --len]; } i = pinv_structure[A.nz_rows[p]]; x[i] = A.nz_values[p]; if (i > k && w[i] < k) { V.nz_rows[V.nz_length++] = i; w[i] = k; } } // apply previously computed Householder vectors to the current columns for (int p = top; p < n; p++) { int i = w[s + p]; QrHelperFunctions_DSCC.applyHouseholder(V, i, beta[i], x); R.nz_rows[R.nz_length] = i; R.nz_values[R.nz_length++] = x[i]; x[i] = 0; if (parent[i] == k) { ImplSparseSparseMult_DSCC.addRowsInAInToC(V, i, V, k, w); } } for (int p = p1; p < V.nz_length; p++) { V.nz_values[p] = x[V.nz_rows[p]]; x[V.nz_rows[p]] = 0; } R.nz_rows[R.nz_length] = k; double max = QrHelperFunctions_DDRM.findMax(V.nz_values, p1, V.nz_length - p1); if (max == 0.0) { singular = true; R.nz_values[R.nz_length] = 0; beta[k] = 0; } else { R.nz_values[R.nz_length] = QrHelperFunctions_DSCC.computeHouseholder(V.nz_values, p1, V.nz_length, max, Beta); beta[k] = Beta.value; } R.nz_length++; } R.col_idx[n] = R.nz_length; V.col_idx[n] = V.nz_length; }