Ejemplo n.º 1
0
        /// <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 &lt; 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;
            }
        }
 /// <summary>
 /// Construct and returns a new empty matrix <i>of the same dynamic type</i> as the receiver, having the specified size.
 /// For example, if the receiver is an instance of type <see cref="DenseDoubleMatrix1D"/> the new matrix must also be of type <see cref="DenseDoubleMatrix1D"/>,
 /// if the receiver is an instance of type <see cref="SparseDoubleMatrix1D"/> the new matrix must also be of type <see cref="SparseDoubleMatrix1D"/>, etc.
 /// In general, the new matrix should have internal parametrization as similar as possible.
 /// </summary>
 /// <param name="size">the number of cell the matrix shall have.</param>
 /// <returns>a new empty matrix of the same dynamic type.</returns>
 public override DoubleMatrix1D Like(int size)
 {
     return(content2D.Like1D(size));
 }