From 7eefdb948c1ff372f85991ff3f9d998e66a554d9 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 11 Mar 2014 13:43:46 +0100 Subject: [PATCH] Migrate JacobiSVD to Solver --- Eigen/src/LU/FullPivLU.h | 4 ++-- Eigen/src/SVD/JacobiSVD.h | 50 ++++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/Eigen/src/LU/FullPivLU.h b/Eigen/src/LU/FullPivLU.h index a06f5702c..78cd9b90f 100644 --- a/Eigen/src/LU/FullPivLU.h +++ b/Eigen/src/LU/FullPivLU.h @@ -702,8 +702,8 @@ struct image_retval > #ifndef EIGEN_PARSED_BY_DOXYGEN template template -void FullPivLU<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const { - +void FullPivLU<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const +{ /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}. * So we proceed as follows: * Step 1: compute c = P * rhs. diff --git a/Eigen/src/SVD/JacobiSVD.h b/Eigen/src/SVD/JacobiSVD.h index eee31ca97..d78583ecc 100644 --- a/Eigen/src/SVD/JacobiSVD.h +++ b/Eigen/src/SVD/JacobiSVD.h @@ -653,6 +653,16 @@ template class JacobiSVD * \note SVD solving is implicitly least-squares. Thus, this method serves both purposes of exact solving and least-squares solving. * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$. */ +#ifdef EIGEN_TEST_EVALUATORS + template + inline const Solve + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "JacobiSVD is not initialized."); + eigen_assert(computeU() && computeV() && "JacobiSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice)."); + return Solve(*this, b.derived()); + } +#else template inline const internal::solve_retval solve(const MatrixBase& b) const @@ -661,6 +671,7 @@ template class JacobiSVD eigen_assert(computeU() && computeV() && "JacobiSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice)."); return internal::solve_retval(*this, b.derived()); } +#endif /** \returns the number of singular values that are not exactly 0 */ Index nonzeroSingularValues() const @@ -734,6 +745,12 @@ template class JacobiSVD inline Index rows() const { return m_rows; } inline Index cols() const { return m_cols; } + + #ifndef EIGEN_PARSED_BY_DOXYGEN + template + EIGEN_DEVICE_FUNC + void _solve_impl(const RhsType &rhs, DstType &dst) const; + #endif private: void allocate(Index rows, Index cols, unsigned int computationOptions); @@ -912,7 +929,27 @@ JacobiSVD::compute(const MatrixType& matrix, unsig return *this; } +#ifndef EIGEN_PARSED_BY_DOXYGEN +template +template +void JacobiSVD<_MatrixType,QRPreconditioner>::_solve_impl(const RhsType &rhs, DstType &dst) const +{ + eigen_assert(rhs.rows() == rows()); + + // A = U S V^* + // So A^{-1} = V S^{-1} U^* + + Matrix tmp; + Index l_rank = rank(); + + tmp.noalias() = m_matrixU.leftCols(l_rank).adjoint() * rhs; + tmp = m_singularValues.head(l_rank).asDiagonal().inverse() * tmp; + dst = m_matrixV.leftCols(l_rank) * tmp; +} +#endif + namespace internal { +#ifndef EIGEN_TEST_EVALUATORS template struct solve_retval, Rhs> : solve_retval_base, Rhs> @@ -922,19 +959,10 @@ struct solve_retval, Rhs> template void evalTo(Dest& dst) const { - eigen_assert(rhs().rows() == dec().rows()); - - // A = U S V^* - // So A^{-1} = V S^{-1} U^* - - Matrix tmp; - Index rank = dec().rank(); - - tmp.noalias() = dec().matrixU().leftCols(rank).adjoint() * rhs(); - tmp = dec().singularValues().head(rank).asDiagonal().inverse() * tmp; - dst = dec().matrixV().leftCols(rank) * tmp; + dec()._solve_impl(rhs(), dst); } }; +#endif } // end namespace internal #ifndef __CUDACC__