2121// <http://www.gnu.org/licenses/>.
2222
2323#include " fastLm.h"
24+ #include < R_ext/Lapack.h>
2425
2526namespace lmsol {
2627 using Rcpp::_;
@@ -54,18 +55,14 @@ namespace lmsol {
5455 return *this ;
5556 }
5657
57- ArrayXd lm::Dplus (const ArrayXd& D ) {
58- ArrayXd Di (m_p );
59- double comp (D .maxCoeff () * threshold ());
60- for (int j = 0 ; j < m_p ; ++j) Di [j] = (D [j] < comp) ? 0 . : 1 ./D [j];
61- m_r = (Di != 0 .).count ();
62- return Di ;
58+ inline ArrayXd lm::Dplus (const ArrayXd& d ) {
59+ ArrayXd di (d. size () );
60+ double comp (d .maxCoeff () * threshold ());
61+ for (int j = 0 ; j < d. size () ; ++j) di [j] = (d [j] < comp) ? 0 . : 1 ./d [j];
62+ m_r = (di != 0 .).count ();
63+ return di ;
6364 }
6465
65- MatrixXd lm::I_p () const {
66- return MatrixXd::Identity (m_p, m_p);
67- }
68-
6966 MatrixXd lm::XtX () const {
7067 return MatrixXd (m_p, m_p).setZero ().selfadjointView <Lower>().
7168 rankUpdate (m_X.adjoint ());
@@ -138,6 +135,31 @@ namespace lmsol {
138135 m_se = Ch.solve (I_p ()).diagonal ().array ().sqrt ();
139136 }
140137
138+ int gesdd (MatrixXd& A, ArrayXd& S, MatrixXd& Vt) {
139+ int info, mone = -1 , m = A.rows (), n = A.cols ();
140+ std::vector<int > iwork (8 * n);
141+ double wrk;
142+ if (m < n || S.size () != n || Vt.rows () != n || Vt.cols () != n)
143+ throw std::invalid_argument (" dimension mismatch in gesvd" );
144+ F77_CALL (dgesdd)(" O" , &m, &n, A.data (), &m, S.data (), A.data (),
145+ &m, Vt.data (), &n, &wrk, &mone, &iwork[0 ], &info);
146+ int lwork (wrk);
147+ std::vector<double > work (lwork);
148+ F77_CALL (dgesdd)(" O" , &m, &n, A.data (), &m, S.data (), A.data (),
149+ &m, Vt.data (), &n, &work[0 ], &lwork, &iwork[0 ], &info);
150+ return info;
151+ }
152+
153+ GESDD::GESDD (const Map<MatrixXd>& X, const Map<VectorXd> &y) : lm(X, y) {
154+ MatrixXd U (X), Vt (m_p, m_p);
155+ ArrayXd S (m_p);
156+ if (gesdd (U, S, Vt)) throw std::runtime_error (" error in gesdd" );
157+ MatrixXd VDi (Vt.adjoint () * Dplus (S).matrix ().asDiagonal ());
158+ m_coef = VDi * U.adjoint () * y;
159+ m_fitted = X * m_coef;
160+ m_se = VDi.rowwise ().norm ();
161+ }
162+
141163 SVD::SVD (const Map<MatrixXd> &X, const Map<VectorXd> &y) : lm(X, y) {
142164 JacobiSVD<MatrixXd> UDV (X.jacobiSvd (ComputeThinU|ComputeThinV));
143165 MatrixXd VDi (UDV.matrixV () *
@@ -157,7 +179,7 @@ namespace lmsol {
157179 m_se = VDi.rowwise ().norm ();
158180 }
159181
160- enum {ColPivQR_t = 0 , QR_t, LLT_t, LDLT_t, SVD_t, SymmEigen_t};
182+ enum {ColPivQR_t = 0 , QR_t, LLT_t, LDLT_t, SVD_t, SymmEigen_t, GESDD_t };
161183
162184 static inline lm do_lm (const Map<MatrixXd> &X, const Map<VectorXd> &y, int type) {
163185 switch (type) {
@@ -173,6 +195,8 @@ namespace lmsol {
173195 return SVD (X, y);
174196 case SymmEigen_t:
175197 return SymmEigen (X, y);
198+ case GESDD_t:
199+ return GESDD (X, y);
176200 }
177201 throw invalid_argument (" invalid type" );
178202 return ColPivQR (X, y); // -Wall
0 commit comments