/// <summary> /// Constructs and returns a new QR decomposition object; computed by Householder reflections; /// The decomposed matrices can be retrieved via instance methods of the returned decomposition object. /// Return a decomposition object to access <i>R</i> and the Householder vectors <i>H</i>, and to compute <i>Q</i>. /// </summary> /// <param name="A">A rectangular matrix.</param> /// <exception cref="ArgumentException">if <i>A.Rows < A.Columns</i>.</exception> public QRDecomposition(DoubleMatrix2D A) { Property.DEFAULT.CheckRectangular(A); Functions F = Functions.functions; // Initialize. QR = A.Copy(); m = A.Rows; n = A.Columns; Rdiag = A.Like1D(n); //Rdiag = new double[n]; DoubleDoubleFunction hypot = Algebra.HypotFunction(); // precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] QRcolumns = new DoubleMatrix1D[n]; DoubleMatrix1D[] QRcolumnsPart = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { QRcolumns[k] = QR.ViewColumn(k); QRcolumnsPart[k] = QR.ViewColumn(k).ViewPart(k, m - k); } // Main loop. for (int k = 0; k < n; k++) { //DoubleMatrix1D QRcolk = QR.ViewColumn(k).ViewPart(k,m-k); // Compute 2-norm of k-th column without under/overflow. double nrm = 0; //if (k<m) nrm = QRcolumnsPart[k].aggregate(hypot,F.identity); for (int i = k; i < m; i++) { // fixes bug reported by [email protected] nrm = Algebra.Hypot(nrm, QR[i, k]); } if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k, k] < 0) { nrm = -nrm; } QRcolumnsPart[k].Assign(F2.Div(nrm)); /* * for (int i = k; i < m; i++) { * QR[i][k] /= nrm; * } */ QR[k, k] = QR[k, k] + 1; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { DoubleMatrix1D QRcolj = QR.ViewColumn(j).ViewPart(k, m - k); double s = QRcolumnsPart[k].ZDotProduct(QRcolj); /* * // fixes bug reported by John Chambers * DoubleMatrix1D QRcolj = QR.ViewColumn(j).ViewPart(k,m-k); * double s = QRcolumnsPart[k].ZDotProduct(QRcolumns[j]); * double s = 0.0; * for (int i = k; i < m; i++) { * s += QR[i][k]*QR[i][j]; * } */ s = -s / QR[k, k]; //QRcolumnsPart[j].Assign(QRcolumns[k], F.PlusMult(s)); for (int i = k; i < m; i++) { QR[i, j] = QR[i, j] + s * QR[i, k]; } } } Rdiag[k] = -nrm; } }