//! QR decompoisition /*! This implementation is based on MINPACK * (<http://www.netlib.org/minpack>, * <http://www.netlib.org/cephes/linalg.tgz>) * * This subroutine uses householder transformations with column * pivoting (optional) to compute a qr factorization of the * m by n matrix A. That is, qrfac determines an orthogonal * matrix q, a permutation matrix p, and an upper trapezoidal * matrix r with diagonal elements of nonincreasing magnitude, * such that A*p = q*r. * * Return value ipvt is an integer array of length n, which * defines the permutation matrix p such that A*p = q*r. * Column j of p is column ipvt(j) of the identity matrix. * * See lmdiff.cpp for further details. */ public static List <int> qrDecomposition(Matrix M, ref Matrix q, ref Matrix r, bool pivot) { Matrix mT = Matrix.transpose(M); int m = M.rows(); int n = M.columns(); List <int> lipvt = new InitializedList <int>(n); Vector rdiag = new Vector(n); Vector wa = new Vector(n); MINPACK.qrfac(m, n, mT, 0, (pivot) ? 1 : 0, ref lipvt, n, ref rdiag, ref rdiag, wa); if (r.columns() != n || r.rows() != n) { r = new Matrix(n, n); } for (int i = 0; i < n; ++i) { r[i, i] = rdiag[i]; if (i < m) { for (int j = i; j < mT.rows() - 1; j++) { r[i, j + 1] = mT[j + 1, i]; } } } if (q.rows() != m || q.columns() != n) { q = new Matrix(m, n); } Vector w = new Vector(m); for (int k = 0; k < m; ++k) { w.Erase(); w[k] = 1.0; for (int j = 0; j < Math.Min(n, m); ++j) { double t3 = mT[j, j]; if (t3.IsNotEqual(0.0)) { double t = 0; for (int kk = j; kk < mT.columns(); kk++) { t += (mT[j, kk] * w[kk]) / t3; } for (int i = j; i < m; ++i) { w[i] -= mT[j, i] * t; } } q[k, j] = w[j]; } } List <int> ipvt = new InitializedList <int>(n); if (pivot) { for (int i = 0; i < n; ++i) { ipvt[i] = lipvt[i]; } } else { for (int i = 0; i < n; ++i) { ipvt[i] = i; } } return(ipvt); }
//! QR decompoisition /*! This implementation is based on MINPACK * (<http://www.netlib.org/minpack>, * <http://www.netlib.org/cephes/linalg.tgz>) * * This subroutine uses householder transformations with column * pivoting (optional) to compute a qr factorization of the * m by n matrix A. That is, qrfac determines an orthogonal * matrix q, a permutation matrix p, and an upper trapezoidal * matrix r with diagonal elements of nonincreasing magnitude, * such that A*p = q*r. * * Return value ipvt is an integer array of length n, which * defines the permutation matrix p such that A*p = q*r. * Column j of p is column ipvt(j) of the identity matrix. * * See lmdiff.cpp for further details. */ //public static List<int> qrDecomposition(Matrix A, Matrix q, Matrix r, bool pivot = true) { public static List <int> qrDecomposition(Matrix M, Matrix q, Matrix r, bool pivot) { Matrix mT = Matrix.transpose(M); int m = M.rows(); int n = M.columns(); List <int> lipvt = new InitializedList <int>(n); Vector rdiag = new Vector(n); Vector wa = new Vector(n); MINPACK.qrfac(m, n, mT, 0, (pivot)?1:0, ref lipvt, n, ref rdiag, ref rdiag, wa); if (r.columns() != n || r.rows() != n) { r = new Matrix(n, n); } for (int i = 0; i < n; ++i) { // std::fill(r.row_begin(i), r.row_begin(i)+i, 0.0); r[i, i] = rdiag[i]; if (i < m) { // std::copy(mT.column_begin(i)+i+1, mT.column_end(i), // r.row_begin(i)+i+1); } else { // std::fill(r.row_begin(i)+i+1, r.row_end(i), 0.0); } } if (q.rows() != m || q.columns() != n) { q = new Matrix(m, n); } Vector w = new Vector(m); //for (int k=0; k < m; ++k) { // std::fill(w.begin(), w.end(), 0.0); // w[k] = 1.0; // for (int j=0; j < Math.Min(n, m); ++j) { // double t3 = mT[j,j]; // if (t3 != 0.0) { // double t // = std::inner_product(mT.row_begin(j)+j, mT.row_end(j), // w.begin()+j, 0.0)/t3; // for (int i=j; i<m; ++i) { // w[i]-=mT[j,i]*t; // } // } // q[k,j] = w[j]; // } // std::fill(q.row_begin(k) + Math.Min(n, m), q.row_end(k), 0.0); //} List <int> ipvt = new InitializedList <int>(n); //if (pivot) { // std::copy(lipvt.get(), lipvt.get()+n, ipvt.begin()); //} //else { // for (int i=0; i < n; ++i) // ipvt[i] = i; //} return(ipvt); }