[Rcpp-commits] r3057 - pkg/RcppEigen/src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Jun 13 23:02:30 CEST 2011
Author: dmbates
Date: 2011-06-13 23:02:30 +0200 (Mon, 13 Jun 2011)
New Revision: 3057
Modified:
pkg/RcppEigen/src/fastLm.cpp
Log:
Handle the rank-deficient case.
Modified: pkg/RcppEigen/src/fastLm.cpp
===================================================================
--- pkg/RcppEigen/src/fastLm.cpp 2011-06-13 21:01:50 UTC (rev 3056)
+++ pkg/RcppEigen/src/fastLm.cpp 2011-06-13 21:02:30 UTC (rev 3057)
@@ -25,7 +25,6 @@
using namespace Eigen;
using namespace Rcpp;
try {
-// static double NaN = std::numeric_limits<double>::quiet_NaN();
NumericMatrix X(Xs);
NumericVector y(ys);
size_t n = X.nrow(), p = X.ncol();
@@ -36,19 +35,36 @@
VectorXd b = Map<VectorXd>(y.begin(), n);
ColPivHouseholderQR<MatrixXd> mqr(A); // decompose the model matrix
- if (!mqr.isInjective())
- throw std::invalid_argument("X is rank deficient");
- size_t r = mqr.rank();
- ptrdiff_t df = n - r;
- VectorXd coef = mqr.solve(b);
- VectorXd fitted = A * coef;
- VectorXd res = b - fitted;
- double s = std::sqrt(res.squaredNorm()/df);
+ size_t r = mqr.rank();
+ ptrdiff_t df = n - r;
+ VectorXd coef(p);
+ VectorXd fitted(n);
+ VectorXd se(p);
+ MatrixXd Rinv;
+ if (r < p) { // Handle the rank-deficient case
+ MatrixXd Atrunc = (A * mqr.colsPermutation()).leftCols(r);
+ HouseholderQR<MatrixXd> QR(Atrunc);
+ VectorXd coefTrunc = QR.solve(b);
+ fitted = Atrunc * coefTrunc;
+ MatrixXd R = QR.matrixQR().topLeftCorner(r, r);
+ Rinv = TriangularView<MatrixXd, Upper>(R).solve(MatrixXd::Identity(r, r));
+ coef.topRows(r) = coefTrunc;
+ std::fill(coef.data() + r, coef.data() + p,
+ std::numeric_limits<double>::quiet_NaN());
+ coef = mqr.colsPermutation() * coef;
+ std::fill(se.data() + r, se.data() + p,
+ std::numeric_limits<double>::quiet_NaN());
+ } else {
+ coef = mqr.solve(b);
+ fitted = A * coef;
+ MatrixXd R = mqr.matrixQR().topRows(p);
+ Rinv = TriangularView<MatrixXd, Upper>(R).solve(MatrixXd::Identity(p, p));
+ }
+ VectorXd res = b - fitted;
+ double s = std::sqrt(res.squaredNorm()/df);
+ se.topRows(r) = Rinv.rowwise().norm() * s;
+ se = mqr.colsPermutation() * se;
- MatrixXd R = mqr.matrixQR().topLeftCorner(r, r); // need to create this explicitly
- MatrixXd Rinv(TriangularView<MatrixXd, Upper>(R).solve(MatrixXd::Identity(r, r)));
- VectorXd se = mqr.colsPermutation() * Rinv.rowwise().norm() * s; // standard errors
-
return List::create(_["coefficients"] = coef,
_["rank"] = r,
_["df"] = df,
More information about the Rcpp-commits
mailing list