diff options
author | Gael Guennebaud <g.gael@free.fr> | 2011-01-26 16:36:07 +0100 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2011-01-26 16:36:07 +0100 |
commit | 98285ba81c8e90c95434bfa262484f2aa5d2664b (patch) | |
tree | 27348c602174eea9b650df8e9d0abca3881ed974 /Eigen | |
parent | 7ef9d82b39b338c814f4c120ef3dea58a244a391 (diff) | |
parent | 76c630d185b4a9eda5261a6f4651cafdebb91508 (diff) |
merge
Diffstat (limited to 'Eigen')
-rw-r--r-- | Eigen/Eigen2Support | 22 | ||||
-rw-r--r-- | Eigen/LU | 4 | ||||
-rw-r--r-- | Eigen/QR | 6 | ||||
-rw-r--r-- | Eigen/SVD | 4 | ||||
-rw-r--r-- | Eigen/src/Core/DenseBase.h | 19 | ||||
-rw-r--r-- | Eigen/src/Core/MatrixBase.h | 31 | ||||
-rw-r--r-- | Eigen/src/Core/SelfAdjointView.h | 40 | ||||
-rw-r--r-- | Eigen/src/Core/TriangularMatrix.h | 72 | ||||
-rw-r--r-- | Eigen/src/Core/Visitor.h | 65 | ||||
-rw-r--r-- | Eigen/src/Core/util/ForwardDeclarations.h | 6 | ||||
-rw-r--r-- | Eigen/src/Eigen2Support/Geometry/Hyperplane.h | 4 | ||||
-rw-r--r-- | Eigen/src/Eigen2Support/LU.h | 133 | ||||
-rw-r--r-- | Eigen/src/Eigen2Support/QR.h | 79 | ||||
-rw-r--r-- | Eigen/src/Eigen2Support/SVD.h | 649 | ||||
-rw-r--r-- | Eigen/src/LU/PartialPivLU.h | 2 | ||||
-rw-r--r-- | Eigen/src/SVD/UpperBidiagonalization.h | 2 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseDiagonalProduct.h | 8 |
17 files changed, 1028 insertions, 118 deletions
diff --git a/Eigen/Eigen2Support b/Eigen/Eigen2Support index 560f1d2ff..9fa378795 100644 --- a/Eigen/Eigen2Support +++ b/Eigen/Eigen2Support @@ -67,16 +67,16 @@ namespace Eigen { EIGEN_USING_MATRIX_TYPEDEFS \ using Eigen::Matrix; \ using Eigen::MatrixBase; \ -namespace ei_random = Eigen::internal::random; \ -namespace ei_real = Eigen::internal::real; \ -namespace ei_imag = Eigen::internal::imag; \ -namespace ei_conj = Eigen::internal::conj; \ -namespace ei_abs = Eigen::internal::abs; \ -namespace ei_abs2 = Eigen::internal::abs2; \ -namespace ei_sqrt = Eigen::internal::sqrt; \ -namespace ei_exp = Eigen::internal::exp; \ -namespace ei_log = Eigen::internal::log; \ -namespace ei_sin = Eigen::internal::sin; \ -namespace ei_cos = Eigen::internal::cos; +using Eigen::ei_random; \ +using Eigen::ei_real; \ +using Eigen::ei_imag; \ +using Eigen::ei_conj; \ +using Eigen::ei_abs; \ +using Eigen::ei_abs2; \ +using Eigen::ei_sqrt; \ +using Eigen::ei_exp; \ +using Eigen::ei_log; \ +using Eigen::ei_sin; \ +using Eigen::ei_cos; #endif // EIGEN2SUPPORT_H @@ -30,6 +30,10 @@ namespace Eigen { #include "src/LU/arch/Inverse_SSE.h" #endif +#ifdef EIGEN2_SUPPORT + #include "src/Eigen2Support/LU.h" +#endif + } // namespace Eigen #include "src/Core/util/EnableMSVCWarnings.h" @@ -29,13 +29,17 @@ namespace Eigen { #include "src/QR/FullPivHouseholderQR.h" #include "src/QR/ColPivHouseholderQR.h" +#ifdef EIGEN2_SUPPORT +#include "src/Eigen2Support/QR.h" +#endif } // namespace Eigen #include "src/Core/util/EnableMSVCWarnings.h" -// FIXME for compatibility we include Eigenvalues here: +#ifdef EIGEN2_SUPPORT #include "Eigenvalues" +#endif #endif // EIGEN_QR_MODULE_H /* vim: set filetype=cpp et sw=2 ts=2 ai: */ @@ -26,6 +26,10 @@ namespace Eigen { #include "src/SVD/JacobiSVD.h" #include "src/SVD/UpperBidiagonalization.h" +#ifdef EIGEN2_SUPPORT +#include "src/Eigen2Support/SVD.h" +#endif + } // namespace Eigen #include "src/Core/util/EnableMSVCWarnings.h" diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 9c3c6432b..b8fa9d1cd 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -415,17 +415,14 @@ template<typename Derived> class DenseBase typename internal::traits<Derived>::Scalar minCoeff() const; typename internal::traits<Derived>::Scalar maxCoeff() const; - typename internal::traits<Derived>::Scalar minCoeff(Index* row, Index* col) const; - typename internal::traits<Derived>::Scalar maxCoeff(Index* row, Index* col) const; - typename internal::traits<Derived>::Scalar minCoeff(Index* index) const; - typename internal::traits<Derived>::Scalar maxCoeff(Index* index) const; - - #ifdef EIGEN2_SUPPORT - typename internal::traits<Derived>::Scalar minCoeff(int* row, int* col) const; - typename internal::traits<Derived>::Scalar maxCoeff(int* row, int* col) const; - typename internal::traits<Derived>::Scalar minCoeff(int* index) const; - typename internal::traits<Derived>::Scalar maxCoeff(int* index) const; - #endif + template<typename IndexType> + typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const; + template<typename IndexType> + typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const; + template<typename IndexType> + typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const; + template<typename IndexType> + typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const; template<typename BinaryOp> typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 40e44c9b3..3b854ca5e 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -243,8 +243,8 @@ template<typename Derived> class MatrixBase typename MatrixBase::template ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const; #ifdef EIGEN2_SUPPORT - template<unsigned int Mode> TriangularView<Derived, Mode> part(); - template<unsigned int Mode> const TriangularView<Derived, Mode> part() const; + template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part(); + template<unsigned int Mode> const typename internal::eigen2_part_return_type<Derived, Mode>::type part() const; // huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead // of an integer constant. Solution: overload the part() method template wrt template parameters list. @@ -334,7 +334,26 @@ template<typename Derived> class MatrixBase const FullPivLU<PlainObject> fullPivLu() const; const PartialPivLU<PlainObject> partialPivLu() const; + + #if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS + const LU<PlainObject> lu() const; + #endif + + #ifdef EIGEN2_SUPPORT + const LU<PlainObject> eigen2_lu() const; + #endif + + #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS const PartialPivLU<PlainObject> lu() const; + #endif + + #ifdef EIGEN2_SUPPORT + template<typename ResultType> + void computeInverse(MatrixBase<ResultType> *result) const { + *result = this->inverse(); + } + #endif + const internal::inverse_impl<Derived> inverse() const; template<typename ResultType> void computeInverseAndDetWithCheck( @@ -361,6 +380,10 @@ template<typename Derived> class MatrixBase const HouseholderQR<PlainObject> householderQr() const; const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const; const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const; + + #ifdef EIGEN2_SUPPORT + const QR<PlainObject> qr() const; + #endif EigenvaluesReturnType eigenvalues() const; RealScalar operatorNorm() const; @@ -369,6 +392,10 @@ template<typename Derived> class MatrixBase JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const; + #ifdef EIGEN2_SUPPORT + SVD<PlainObject> svd() const; + #endif + /////////// Geometry module /////////// template<typename OtherDerived> diff --git a/Eigen/src/Core/SelfAdjointView.h b/Eigen/src/Core/SelfAdjointView.h index 5d8468884..0e9872bf5 100644 --- a/Eigen/src/Core/SelfAdjointView.h +++ b/Eigen/src/Core/SelfAdjointView.h @@ -46,13 +46,14 @@ template<typename MatrixType, unsigned int UpLo> struct traits<SelfAdjointView<MatrixType, UpLo> > : traits<MatrixType> { typedef typename nested<MatrixType>::type MatrixTypeNested; - typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; + typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned; typedef MatrixType ExpressionType; + typedef typename MatrixType::PlainObject DenseMatrixType; enum { Mode = UpLo | SelfAdjoint, - Flags = _MatrixTypeNested::Flags & (HereditaryBits) + Flags = MatrixTypeNestedCleaned::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit)), // FIXME these flags should be preserved - CoeffReadCost = _MatrixTypeNested::CoeffReadCost + CoeffReadCost = MatrixTypeNestedCleaned::CoeffReadCost }; }; } @@ -68,6 +69,8 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView public: typedef TriangularBase<SelfAdjointView> Base; + typedef typename internal::traits<SelfAdjointView>::MatrixTypeNested MatrixTypeNested; + typedef typename internal::traits<SelfAdjointView>::MatrixTypeNestedCleaned MatrixTypeNestedCleaned; /** \brief The type of coefficients in this matrix */ typedef typename internal::traits<SelfAdjointView>::Scalar Scalar; @@ -106,10 +109,10 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView } /** \internal */ - const MatrixType& _expression() const { return m_matrix; } + const MatrixTypeNestedCleaned& _expression() const { return m_matrix; } - const MatrixType& nestedExpression() const { return m_matrix; } - MatrixType& nestedExpression() { return const_cast<MatrixType&>(m_matrix); } + const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } + MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); } /** Efficient self-adjoint matrix times vector/matrix product */ template<typename OtherDerived> @@ -171,9 +174,32 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView EigenvaluesReturnType eigenvalues() const; RealScalar operatorNorm() const; + + #ifdef EIGEN2_SUPPORT + template<typename OtherDerived> + SelfAdjointView& operator=(const MatrixBase<OtherDerived>& other) + { + enum { + OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper + }; + m_matrix.const_cast_derived().template triangularView<UpLo>() = other; + m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.adjoint(); + return *this; + } + template<typename OtherMatrixType, unsigned int OtherMode> + SelfAdjointView& operator=(const TriangularView<OtherMatrixType, OtherMode>& other) + { + enum { + OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper + }; + m_matrix.const_cast_derived().template triangularView<UpLo>() = other.toDenseMatrix(); + m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.toDenseMatrix().adjoint(); + return *this; + } + #endif protected: - const typename MatrixType::Nested m_matrix; + const MatrixTypeNested m_matrix; }; diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h index ce5b53631..40dd2e4bc 100644 --- a/Eigen/src/Core/TriangularMatrix.h +++ b/Eigen/src/Core/TriangularMatrix.h @@ -48,6 +48,7 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived> typedef typename internal::traits<Derived>::Scalar Scalar; typedef typename internal::traits<Derived>::StorageKind StorageKind; typedef typename internal::traits<Derived>::Index Index; + typedef typename internal::traits<Derived>::DenseMatrixType DenseMatrixType; inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); } @@ -88,6 +89,13 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived> template<typename DenseDerived> void evalToLazy(MatrixBase<DenseDerived> &other) const; + DenseMatrixType toDenseMatrix() const + { + DenseMatrixType res(rows(), cols()); + evalToLazy(res); + return res; + } + protected: void check_coordinates(Index row, Index col) const @@ -135,12 +143,14 @@ template<typename MatrixType, unsigned int _Mode> struct traits<TriangularView<MatrixType, _Mode> > : traits<MatrixType> { typedef typename nested<MatrixType>::type MatrixTypeNested; - typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; + typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedNonRef; + typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned; typedef MatrixType ExpressionType; + typedef typename MatrixType::PlainObject DenseMatrixType; enum { Mode = _Mode, - Flags = (_MatrixTypeNested::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode, - CoeffReadCost = _MatrixTypeNested::CoeffReadCost + Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode, + CoeffReadCost = MatrixTypeNestedCleaned::CoeffReadCost }; }; } @@ -159,11 +169,13 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView typedef typename internal::traits<TriangularView>::Scalar Scalar; typedef _MatrixType MatrixType; - typedef typename MatrixType::PlainObject DenseMatrixType; + typedef typename internal::traits<TriangularView>::DenseMatrixType DenseMatrixType; protected: - typedef typename MatrixType::Nested MatrixTypeNested; - typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested; + typedef typename internal::traits<TriangularView>::MatrixTypeNested MatrixTypeNested; + typedef typename internal::traits<TriangularView>::MatrixTypeNestedNonRef MatrixTypeNestedNonRef; + typedef typename internal::traits<TriangularView>::MatrixTypeNestedCleaned MatrixTypeNestedCleaned; + typedef typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type MatrixConjugateReturnType; public: @@ -226,8 +238,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView return m_matrix.const_cast_derived().coeffRef(row, col); } - const MatrixType& nestedExpression() const { return m_matrix; } - MatrixType& nestedExpression() { return const_cast<MatrixType&>(m_matrix); } + const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } + MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); } /** Assigns a triangular matrix to a triangular part of a dense matrix */ template<typename OtherDerived> @@ -269,13 +281,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView inline const TriangularView<Transpose<MatrixType>,TransposeMode> transpose() const { return m_matrix.transpose(); } - DenseMatrixType toDenseMatrix() const - { - DenseMatrixType res(rows(), cols()); - evalToLazy(res); - return res; - } - /** Efficient triangular matrix times vector/matrix product */ template<typename OtherDerived> TriangularProduct<Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime> @@ -310,18 +315,18 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView const typename eigen2_product_return_type<OtherMatrixType>::type operator*(const TriangularView<OtherMatrixType, Mode>& rhs) const { - return toDenseMatrix() * rhs.toDenseMatrix(); + return this->toDenseMatrix() * rhs.toDenseMatrix(); } template<typename OtherMatrixType> bool isApprox(const TriangularView<OtherMatrixType, Mode>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const { - return toDenseMatrix().isApprox(other.toDenseMatrix(), precision); + return this->toDenseMatrix().isApprox(other.toDenseMatrix(), precision); } template<typename OtherDerived> bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const { - return toDenseMatrix().isApprox(other, precision); + return this->toDenseMatrix().isApprox(other, precision); } #endif // EIGEN2_SUPPORT @@ -342,15 +347,15 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView void solveInPlace(const MatrixBase<OtherDerived>& other) const { return solveInPlace<OnTheLeft>(other); } - const SelfAdjointView<_MatrixTypeNested,Mode> selfadjointView() const + const SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() const { EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR); - return SelfAdjointView<_MatrixTypeNested,Mode>(m_matrix); + return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix); } - SelfAdjointView<_MatrixTypeNested,Mode> selfadjointView() + SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() { EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR); - return SelfAdjointView<_MatrixTypeNested,Mode>(m_matrix); + return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix); } template<typename OtherDerived> @@ -692,7 +697,7 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const eigen_assert(this->rows() == other.rows() && this->cols() == other.cols()); internal::triangular_assignment_selector - <DenseDerived, typename internal::traits<Derived>::ExpressionType, Derived::Mode, + <DenseDerived, typename internal::traits<Derived>::MatrixTypeNestedCleaned, Derived::Mode, unroll ? int(DenseDerived::SizeAtCompileTime) : Dynamic, true // clear the opposite triangular part >::run(other.derived(), derived().nestedExpression()); @@ -707,10 +712,27 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const ***************************************************************************/ #ifdef EIGEN2_SUPPORT + +// implementation of part<>(), including the SelfAdjoint case. + +namespace internal { +template<typename MatrixType, unsigned int Mode> +struct eigen2_part_return_type +{ + typedef TriangularView<MatrixType, Mode> type; +}; + +template<typename MatrixType> +struct eigen2_part_return_type<MatrixType, SelfAdjoint> +{ + typedef SelfAdjointView<MatrixType, Upper> type; +}; +} + /** \deprecated use MatrixBase::triangularView() */ template<typename Derived> template<unsigned int Mode> -const TriangularView<Derived, Mode> MatrixBase<Derived>::part() const +const typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part() const { return derived(); } @@ -718,7 +740,7 @@ const TriangularView<Derived, Mode> MatrixBase<Derived>::part() const /** \deprecated use MatrixBase::triangularView() */ template<typename Derived> template<unsigned int Mode> -TriangularView<Derived, Mode> MatrixBase<Derived>::part() +typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part() { return derived(); } diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h index 556c6fcd7..378ebcba1 100644 --- a/Eigen/src/Core/Visitor.h +++ b/Eigen/src/Core/Visitor.h @@ -183,8 +183,9 @@ struct functor_traits<max_coeff_visitor<Scalar> > { * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff() */ template<typename Derived> +template<typename IndexType> typename internal::traits<Derived>::Scalar -DenseBase<Derived>::minCoeff(Index* row, Index* col) const +DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const { internal::min_coeff_visitor<Derived> minVisitor; this->visit(minVisitor); @@ -196,11 +197,12 @@ DenseBase<Derived>::minCoeff(Index* row, Index* col) const /** \returns the minimum of all coefficients of *this * and puts in *index its location. * - * \sa DenseBase::minCoeff(Index*,Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff() + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff() */ template<typename Derived> +template<typename IndexType> typename internal::traits<Derived>::Scalar -DenseBase<Derived>::minCoeff(Index* index) const +DenseBase<Derived>::minCoeff(IndexType* index) const { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) internal::min_coeff_visitor<Derived> minVisitor; @@ -212,11 +214,12 @@ DenseBase<Derived>::minCoeff(Index* index) const /** \returns the maximum of all coefficients of *this * and puts in *row and *col its location. * - * \sa DenseBase::minCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::maxCoeff() + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff() */ template<typename Derived> +template<typename IndexType> typename internal::traits<Derived>::Scalar -DenseBase<Derived>::maxCoeff(Index* row, Index* col) const +DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const { internal::max_coeff_visitor<Derived> maxVisitor; this->visit(maxVisitor); @@ -228,11 +231,12 @@ DenseBase<Derived>::maxCoeff(Index* row, Index* col) const /** \returns the maximum of all coefficients of *this * and puts in *index its location. * - * \sa DenseBase::maxCoeff(Index*,Index*), DenseBase::minCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::maxCoeff() + * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff() */ template<typename Derived> +template<typename IndexType> typename internal::traits<Derived>::Scalar -DenseBase<Derived>::maxCoeff(Index* index) const +DenseBase<Derived>::maxCoeff(IndexType* index) const { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) internal::max_coeff_visitor<Derived> maxVisitor; @@ -241,51 +245,4 @@ DenseBase<Derived>::maxCoeff(Index* index) const return maxVisitor.res; } -#ifdef EIGEN2_SUPPORT - -template<typename Derived> -typename internal::traits<Derived>::Scalar -DenseBase<Derived>::minCoeff(int* row, int* col) const -{ - Index r, c; - Scalar result = this->minCoeff(&r, &c); - *row = int(r); - *col = int(c); - return result; -} - -template<typename Derived> -typename internal::traits<Derived>::Scalar -DenseBase<Derived>::minCoeff(int* index) const -{ - Index i; - Scalar result = this->minCoeff(&i); - *index = int(i); - return result; -} - -template<typename Derived> -typename internal::traits<Derived>::Scalar -DenseBase<Derived>::maxCoeff(int* row, int* col) const -{ - Index r, c; - Scalar result = this->maxCoeff(&r, &c); - *row = int(r); - *col = int(c); - return result; -} - -template<typename Derived> -typename internal::traits<Derived>::Scalar -DenseBase<Derived>::maxCoeff(int* index) const -{ - Index i; - Scalar result = this->maxCoeff(&i); - *index = int(i); - return result; -} - -#endif // EIGEN2_SUPPORT - - #endif // EIGEN_VISITOR_H diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index d4eb2c31c..5a2de7095 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -270,6 +270,12 @@ struct stem_function #ifdef EIGEN2_SUPPORT template<typename ExpressionType> class Cwise; template<typename MatrixType> class Minor; +template<typename MatrixType> class LU; +template<typename MatrixType> class QR; +template<typename MatrixType> class SVD; +namespace internal { +template<typename MatrixType, unsigned int Mode> struct eigen2_part_return_type; +} #endif #endif // EIGEN_FORWARDDECLARATIONS_H diff --git a/Eigen/src/Eigen2Support/Geometry/Hyperplane.h b/Eigen/src/Eigen2Support/Geometry/Hyperplane.h index a9a46e33f..420b30fe9 100644 --- a/Eigen/src/Eigen2Support/Geometry/Hyperplane.h +++ b/Eigen/src/Eigen2Support/Geometry/Hyperplane.h @@ -122,7 +122,7 @@ public: ~Hyperplane() {} /** \returns the dimension in which the plane holds */ - inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : AmbientDimAtCompileTime; } + inline int dim() const { return int(AmbientDimAtCompileTime)==Dynamic ? m_coeffs.size()-1 : int(AmbientDimAtCompileTime); } /** normalizes \c *this */ void normalize(void) @@ -147,7 +147,7 @@ public: /** \returns a constant reference to the unit normal vector of the plane, which corresponds * to the linear part of the implicit equation. */ - inline const NormalReturnType normal() const { return NormalReturnType(m_coeffs,0,0,dim(),1); } + inline const NormalReturnType normal() const { return NormalReturnType(*const_cast<Coefficients*>(&m_coeffs),0,0,dim(),1); } /** \returns a non-constant reference to the unit normal vector of the plane, which corresponds * to the linear part of the implicit equation. diff --git a/Eigen/src/Eigen2Support/LU.h b/Eigen/src/Eigen2Support/LU.h new file mode 100644 index 000000000..c23c11baa --- /dev/null +++ b/Eigen/src/Eigen2Support/LU.h @@ -0,0 +1,133 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN2_LU_H +#define EIGEN2_LU_H + +template<typename MatrixType> +class LU : public FullPivLU<MatrixType> +{ + public: + + typedef typename MatrixType::Scalar Scalar; + typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; + typedef Matrix<int, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> IntRowVectorType; + typedef Matrix<int, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> IntColVectorType; + typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> RowVectorType; + typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> ColVectorType; + + typedef Matrix<typename MatrixType::Scalar, + MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix + // so that the product "matrix * kernel = zero" makes sense + Dynamic, // we don't know at compile-time the dimension of the kernel + MatrixType::Options, + MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter + MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number + // of columns of the original matrix + > KernelResultType; + + typedef Matrix<typename MatrixType::Scalar, + MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number + // of rows of the original matrix + Dynamic, // we don't know at compile time the dimension of the image (the rank) + MatrixType::Options, + MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix, + MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns. + > ImageResultType; + + typedef FullPivLU<MatrixType> Base; + LU() : Base() {} + + template<typename T> + explicit LU(const T& t) : Base(t), m_originalMatrix(t) {} + + template<typename OtherDerived, typename ResultType> + bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const + { + *result = static_cast<const Base*>(this)->solve(b); + return true; + } + + template<typename ResultType> + inline void computeInverse(ResultType *result) const + { + solve(MatrixType::Identity(this->rows(), this->cols()), result); + } + + template<typename KernelMatrixType> + void computeKernel(KernelMatrixType *result) const + { + *result = static_cast<const Base*>(this)->kernel(); + } + + template<typename ImageMatrixType> + void computeImage(ImageMatrixType *result) const + { + *result = static_cast<const Base*>(this)->image(m_originalMatrix); + } + + const ImageResultType image() const + { + return static_cast<const Base*>(this)->image(m_originalMatrix); + } + + const MatrixType& m_originalMatrix; +}; + +#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS +/** \lu_module + * + * Synonym of partialPivLu(). + * + * \return the partial-pivoting LU decomposition of \c *this. + * + * \sa class PartialPivLU + */ +template<typename Derived> +inline const LU<typename MatrixBase<Derived>::PlainObject> +MatrixBase<Derived>::lu() const +{ + return LU<PlainObject>(eval()); +} +#endif + +#ifdef EIGEN2_SUPPORT +/** \lu_module + * + * Synonym of partialPivLu(). + * + * \return the partial-pivoting LU decomposition of \c *this. + * + * \sa class PartialPivLU + */ +template<typename Derived> +inline const LU<typename MatrixBase<Derived>::PlainObject> +MatrixBase<Derived>::eigen2_lu() const +{ + return LU<PlainObject>(eval()); +} +#endif + + +#endif // EIGEN2_LU_H diff --git a/Eigen/src/Eigen2Support/QR.h b/Eigen/src/Eigen2Support/QR.h new file mode 100644 index 000000000..64f5d5ccb --- /dev/null +++ b/Eigen/src/Eigen2Support/QR.h @@ -0,0 +1,79 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr> +// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN2_QR_H +#define EIGEN2_QR_H + +template<typename MatrixType> +class QR : public HouseholderQR<MatrixType> +{ + public: + + typedef HouseholderQR<MatrixType> Base; + typedef Block<const MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType; + + QR() : Base() {} + + template<typename T> + explicit QR(const T& t) : Base(t) {} + + template<typename OtherDerived, typename ResultType> + bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const + { + *result = static_cast<const Base*>(this)->solve(b); + return true; + } + + MatrixType matrixQ(void) const { + MatrixType ret = MatrixType::Identity(this->rows(), this->cols()); + ret = this->householderQ() * ret; + return ret; + } + + bool isFullRank() const { + return true; + } + + const TriangularView<MatrixRBlockType, UpperTriangular> + matrixR(void) const + { + int cols = this->cols(); + return MatrixRBlockType(this->matrixQR(), 0, 0, cols, cols).template triangularView<UpperTriangular>(); + } +}; + +/** \return the QR decomposition of \c *this. + * + * \sa class QR + */ +template<typename Derived> +const QR<typename MatrixBase<Derived>::PlainObject> +MatrixBase<Derived>::qr() const +{ + return QR<PlainObject>(eval()); +} + + +#endif // EIGEN2_QR_H diff --git a/Eigen/src/Eigen2Support/SVD.h b/Eigen/src/Eigen2Support/SVD.h new file mode 100644 index 000000000..dfb43ac7c --- /dev/null +++ b/Eigen/src/Eigen2Support/SVD.h @@ -0,0 +1,649 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN_SVD_H +#define EIGEN_SVD_H + +/** \ingroup SVD_Module + * \nonstableyet + * + * \class SVD + * + * \brief Standard SVD decomposition of a matrix and associated features + * + * \param MatrixType the type of the matrix of which we are computing the SVD decomposition + * + * This class performs a standard SVD decomposition of a real matrix A of size \c M x \c N + * with \c M \>= \c N. + * + * + * \sa MatrixBase::SVD() + */ +template<typename MatrixType> class SVD +{ + private: + typedef typename MatrixType::Scalar Scalar; + typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; + + enum { + PacketSize = internal::packet_traits<Scalar>::size, + AlignmentMask = int(PacketSize)-1, + MinSize = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime) + }; + + typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVector; + typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> RowVector; + + typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MinSize> MatrixUType; + typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixVType; + typedef Matrix<Scalar, MinSize, 1> SingularValuesType; + + public: + + SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7 + + SVD(const MatrixType& matrix) + : m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())), + m_matV(matrix.cols(),matrix.cols()), + m_sigma(std::min(matrix.rows(),matrix.cols())) + { + compute(matrix); + } + + template<typename OtherDerived, typename ResultType> + bool solve(const MatrixBase<OtherDerived> &b, ResultType* result) const; + + const MatrixUType& matrixU() const { return m_matU; } + const SingularValuesType& singularValues() const { return m_sigma; } + const MatrixVType& matrixV() const { return m_matV; } + + void compute(const MatrixType& matrix); + SVD& sort(); + + template<typename UnitaryType, typename PositiveType> + void computeUnitaryPositive(UnitaryType *unitary, PositiveType *positive) const; + template<typename PositiveType, typename UnitaryType> + void computePositiveUnitary(PositiveType *positive, UnitaryType *unitary) const; + template<typename RotationType, typename ScalingType> + void computeRotationScaling(RotationType *unitary, ScalingType *positive) const; + template<typename ScalingType, typename RotationType> + void computeScalingRotation(ScalingType *positive, RotationType *unitary) const; + + protected: + /** \internal */ + MatrixUType m_matU; + /** \internal */ + MatrixVType m_matV; + /** \internal */ + SingularValuesType m_sigma; +}; + +/** Computes / recomputes the SVD decomposition A = U S V^* of \a matrix + * + * \note this code has been adapted from JAMA (public domain) + */ +template<typename MatrixType> +void SVD<MatrixType>::compute(const MatrixType& matrix) +{ + const int m = matrix.rows(); + const int n = matrix.cols(); + const int nu = std::min(m,n); + ei_assert(m>=n && "In Eigen 2.0, SVD only works for MxN matrices with M>=N. Sorry!"); + ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices"); + + m_matU.resize(m, nu); + m_matU.setZero(); + m_sigma.resize(std::min(m,n)); + m_matV.resize(n,n); + + RowVector e(n); + ColVector work(m); + MatrixType matA(matrix); + const bool wantu = true; + const bool wantv = true; + int i=0, j=0, k=0; + + // Reduce A to bidiagonal form, storing the diagonal elements + // in s and the super-diagonal elements in e. + int nct = std::min(m-1,n); + int nrt = std::max(0,std::min(n-2,m)); + for (k = 0; k < std::max(nct,nrt); ++k) + { + if (k < nct) + { + // Compute the transformation for the k-th column and + // place the k-th diagonal in m_sigma[k]. + m_sigma[k] = matA.col(k).end(m-k).norm(); + if (m_sigma[k] != 0.0) // FIXME + { + if (matA(k,k) < 0.0) + m_sigma[k] = -m_sigma[k]; + matA.col(k).end(m-k) /= m_sigma[k]; + matA(k,k) += 1.0; + } + m_sigma[k] = -m_sigma[k]; + } + + for (j = k+1; j < n; ++j) + { + if ((k < nct) && (m_sigma[k] != 0.0)) + { + // Apply the transformation. + Scalar t = matA.col(k).end(m-k).dot(matA.col(j).end(m-k)); // FIXME dot product or cwise prod + .sum() ?? + t = -t/matA(k,k); + matA.col(j).end(m-k) += t * matA.col(k).end(m-k); + } + + // Place the k-th row of A into e for the + // subsequent calculation of the row transformation. + e[j] = matA(k,j); + } + + // Place the transformation in U for subsequent back multiplication. + if (wantu & (k < nct)) + m_matU.col(k).end(m-k) = matA.col(k).end(m-k); + + if (k < nrt) + { + // Compute the k-th row transformation and place the + // k-th super-diagonal in e[k]. + e[k] = e.end(n-k-1).norm(); + if (e[k] != 0.0) + { + if (e[k+1] < 0.0) + e[k] = -e[k]; + e.end(n-k-1) /= e[k]; + e[k+1] += 1.0; + } + e[k] = -e[k]; + if ((k+1 < m) & (e[k] != 0.0)) + { + // Apply the transformation. + work.end(m-k-1) = matA.corner(BottomRight,m-k-1,n-k-1) * e.end(n-k-1); + for (j = k+1; j < n; ++j) + matA.col(j).end(m-k-1) += (-e[j]/e[k+1]) * work.end(m-k-1); + } + + // Place the transformation in V for subsequent back multiplication. + if (wantv) + m_matV.col(k).end(n-k-1) = e.end(n-k-1); + } + } + + + // Set up the final bidiagonal matrix or order p. + int p = std::min(n,m+1); + if (nct < n) + m_sigma[nct] = matA(nct,nct); + if (m < p) + m_sigma[p-1] = 0.0; + if (nrt+1 < p) + e[nrt] = matA(nrt,p-1); + e[p-1] = 0.0; + + // If required, generate U. + if (wantu) + { + for (j = nct; j < nu; ++j) + { + m_matU.col(j).setZero(); + m_matU(j,j) = 1.0; + } + for (k = nct-1; k >= 0; k--) + { + if (m_sigma[k] != 0.0) + { + for (j = k+1; j < nu; ++j) + { + Scalar t = m_matU.col(k).end(m-k).dot(m_matU.col(j).end(m-k)); // FIXME is it really a dot product we want ? + t = -t/m_matU(k,k); + m_matU.col(j).end(m-k) += t * m_matU.col(k).end(m-k); + } + m_matU.col(k).end(m-k) = - m_matU.col(k).end(m-k); + m_matU(k,k) = Scalar(1) + m_matU(k,k); + if (k-1>0) + m_matU.col(k).start(k-1).setZero(); + } + else + { + m_matU.col(k).setZero(); + m_matU(k,k) = 1.0; + } + } + } + + // If required, generate V. + if (wantv) + { + for (k = n-1; k >= 0; k--) + { + if ((k < nrt) & (e[k] != 0.0)) + { + for (j = k+1; j < nu; ++j) + { + Scalar t = m_matV.col(k).end(n-k-1).dot(m_matV.col(j).end(n-k-1)); // FIXME is it really a dot product we want ? + t = -t/m_matV(k+1,k); + m_matV.col(j).end(n-k-1) += t * m_matV.col(k).end(n-k-1); + } + } + m_matV.col(k).setZero(); + m_matV(k,k) = 1.0; + } + } + + // Main iteration loop for the singular values. + int pp = p-1; + int iter = 0; + Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52)); + while (p > 0) + { + int k=0; + int kase=0; + + // Here is where a test for too many iterations would go. + + // This section of the program inspects for + // negligible elements in the s and e arrays. On + // completion the variables kase and k are set as follows. + + // kase = 1 if s(p) and e[k-1] are negligible and k<p + // kase = 2 if s(k) is negligible and k<p + // kase = 3 if e[k-1] is negligible, k<p, and + // s(k), ..., s(p) are not negligible (qr step). + // kase = 4 if e(p-1) is negligible (convergence). + + for (k = p-2; k >= -1; --k) + { + if (k == -1) + break; + if (ei_abs(e[k]) <= eps*(ei_abs(m_sigma[k]) + ei_abs(m_sigma[k+1]))) + { + e[k] = 0.0; + break; + } + } + if (k == p-2) + { + kase = 4; + } + else + { + int ks; + for (ks = p-1; ks >= k; --ks) + { + if (ks == k) + break; + Scalar t = (ks != p ? ei_abs(e[ks]) : Scalar(0)) + (ks != k+1 ? ei_abs(e[ks-1]) : Scalar(0)); + if (ei_abs(m_sigma[ks]) <= eps*t) + { + m_sigma[ks] = 0.0; + break; + } + } + if (ks == k) + { + kase = 3; + } + else if (ks == p-1) + { + kase = 1; + } + else + { + kase = 2; + k = ks; + } + } + ++k; + + // Perform the task indicated by kase. + switch (kase) + { + + // Deflate negligible s(p). + case 1: + { + Scalar f(e[p-2]); + e[p-2] = 0.0; + for (j = p-2; j >= k; --j) + { + Scalar t(internal::hypot(m_sigma[j],f)); + Scalar cs(m_sigma[j]/t); + Scalar sn(f/t); + m_sigma[j] = t; + if (j != k) + { + f = -sn*e[j-1]; + e[j-1] = cs*e[j-1]; + } + if (wantv) + { + for (i = 0; i < n; ++i) + { + t = cs*m_matV(i,j) + sn*m_matV(i,p-1); + m_matV(i,p-1) = -sn*m_matV(i,j) + cs*m_matV(i,p-1); + m_matV(i,j) = t; + } + } + } + } + break; + + // Split at negligible s(k). + case 2: + { + Scalar f(e[k-1]); + e[k-1] = 0.0; + for (j = k; j < p; ++j) + { + Scalar t(internal::hypot(m_sigma[j],f)); + Scalar cs( m_sigma[j]/t); + Scalar sn(f/t); + m_sigma[j] = t; + f = -sn*e[j]; + e[j] = cs*e[j]; + if (wantu) + { + for (i = 0; i < m; ++i) + { + t = cs*m_matU(i,j) + sn*m_matU(i,k-1); + m_matU(i,k-1) = -sn*m_matU(i,j) + cs*m_matU(i,k-1); + m_matU(i,j) = t; + } + } + } + } + break; + + // Perform one qr step. + case 3: + { + // Calculate the shift. + Scalar scale = std::max(std::max(std::max(std::max( + ei_abs(m_sigma[p-1]),ei_abs(m_sigma[p-2])),ei_abs(e[p-2])), + ei_abs(m_sigma[k])),ei_abs(e[k])); + Scalar sp = m_sigma[p-1]/scale; + Scalar spm1 = m_sigma[p-2]/scale; + Scalar epm1 = e[p-2]/scale; + Scalar sk = m_sigma[k]/scale; + Scalar ek = e[k]/scale; + Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/Scalar(2); + Scalar c = (sp*epm1)*(sp*epm1); + Scalar shift = 0.0; + if ((b != 0.0) || (c != 0.0)) + { + shift = ei_sqrt(b*b + c); + if (b < 0.0) + shift = -shift; + shift = c/(b + shift); + } + Scalar f = (sk + sp)*(sk - sp) + shift; + Scalar g = sk*ek; + + // Chase zeros. + + for (j = k; j < p-1; ++j) + { + Scalar t = internal::hypot(f,g); + Scalar cs = f/t; + Scalar sn = g/t; + if (j != k) + e[j-1] = t; + f = cs*m_sigma[j] + sn*e[j]; + e[j] = cs*e[j] - sn*m_sigma[j]; + g = sn*m_sigma[j+1]; + m_sigma[j+1] = cs*m_sigma[j+1]; + if (wantv) + { + for (i = 0; i < n; ++i) + { + t = cs*m_matV(i,j) + sn*m_matV(i,j+1); + m_matV(i,j+1) = -sn*m_matV(i,j) + cs*m_matV(i,j+1); + m_matV(i,j) = t; + } + } + t = internal::hypot(f,g); + cs = f/t; + sn = g/t; + m_sigma[j] = t; + f = cs*e[j] + sn*m_sigma[j+1]; + m_sigma[j+1] = -sn*e[j] + cs*m_sigma[j+1]; + g = sn*e[j+1]; + e[j+1] = cs*e[j+1]; + if (wantu && (j < m-1)) + { + for (i = 0; i < m; ++i) + { + t = cs*m_matU(i,j) + sn*m_matU(i,j+1); + m_matU(i,j+1) = -sn*m_matU(i,j) + cs*m_matU(i,j+1); + m_matU(i,j) = t; + } + } + } + e[p-2] = f; + iter = iter + 1; + } + break; + + // Convergence. + case 4: + { + // Make the singular values positive. + if (m_sigma[k] <= 0.0) + { + m_sigma[k] = m_sigma[k] < Scalar(0) ? -m_sigma[k] : Scalar(0); + if (wantv) + m_matV.col(k).start(pp+1) = -m_matV.col(k).start(pp+1); + } + + // Order the singular values. + while (k < pp) + { + if (m_sigma[k] >= m_sigma[k+1]) + break; + Scalar t = m_sigma[k]; + m_sigma[k] = m_sigma[k+1]; + m_sigma[k+1] = t; + if (wantv && (k < n-1)) + m_matV.col(k).swap(m_matV.col(k+1)); + if (wantu && (k < m-1)) + m_matU.col(k).swap(m_matU.col(k+1)); + ++k; + } + iter = 0; + p--; + } + break; + } // end big switch + } // end iterations +} + +template<typename MatrixType> +SVD<MatrixType>& SVD<MatrixType>::sort() +{ + int mu = m_matU.rows(); + int mv = m_matV.rows(); + int n = m_matU.cols(); + + for (int i=0; i<n; ++i) + { + int k = i; + Scalar p = m_sigma.coeff(i); + + for (int j=i+1; j<n; ++j) + { + if (m_sigma.coeff(j) > p) + { + k = j; + p = m_sigma.coeff(j); + } + } + if (k != i) + { + m_sigma.coeffRef(k) = m_sigma.coeff(i); // i.e. + m_sigma.coeffRef(i) = p; // swaps the i-th and the k-th elements + + int j = mu; + for(int s=0; j!=0; ++s, --j) + std::swap(m_matU.coeffRef(s,i), m_matU.coeffRef(s,k)); + + j = mv; + for (int s=0; j!=0; ++s, --j) + std::swap(m_matV.coeffRef(s,i), m_matV.coeffRef(s,k)); + } + } + return *this; +} + +/** \returns the solution of \f$ A x = b \f$ using the current SVD decomposition of A. + * The parts of the solution corresponding to zero singular values are ignored. + * + * \sa MatrixBase::svd(), LU::solve(), LLT::solve() + */ +template<typename MatrixType> +template<typename OtherDerived, typename ResultType> +bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const +{ + const int rows = m_matU.rows(); + ei_assert(b.rows() == rows); + + Scalar maxVal = m_sigma.cwise().abs().maxCoeff(); + for (int j=0; j<b.cols(); ++j) + { + Matrix<Scalar,MatrixUType::RowsAtCompileTime,1> aux = m_matU.transpose() * b.col(j); + + for (int i = 0; i <m_matU.cols(); ++i) + { + Scalar si = m_sigma.coeff(i); + if (ei_isMuchSmallerThan(ei_abs(si),maxVal)) + aux.coeffRef(i) = 0; + else + aux.coeffRef(i) /= si; + } + + result->col(j) = m_matV * aux; + } + return true; +} + +/** Computes the polar decomposition of the matrix, as a product unitary x positive. + * + * If either pointer is zero, the corresponding computation is skipped. + * + * Only for square matrices. + * + * \sa computePositiveUnitary(), computeRotationScaling() + */ +template<typename MatrixType> +template<typename UnitaryType, typename PositiveType> +void SVD<MatrixType>::computeUnitaryPositive(UnitaryType *unitary, + PositiveType *positive) const +{ + ei_assert(m_matU.cols() == m_matV.cols() && "Polar decomposition is only for square matrices"); + if(unitary) *unitary = m_matU * m_matV.adjoint(); + if(positive) *positive = m_matV * m_sigma.asDiagonal() * m_matV.adjoint(); +} + +/** Computes the polar decomposition of the matrix, as a product positive x unitary. + * + * If either pointer is zero, the corresponding computation is skipped. + * + * Only for square matrices. + * + * \sa computeUnitaryPositive(), computeRotationScaling() + */ +template<typename MatrixType> +template<typename UnitaryType, typename PositiveType> +void SVD<MatrixType>::computePositiveUnitary(UnitaryType *positive, + PositiveType *unitary) const +{ + ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices"); + if(unitary) *unitary = m_matU * m_matV.adjoint(); + if(positive) *positive = m_matU * m_sigma.asDiagonal() * m_matU.adjoint(); +} + +/** decomposes the matrix as a product rotation x scaling, the scaling being + * not necessarily positive. + * + * If either pointer is zero, the corresponding computation is skipped. + * + * This method requires the Geometry module. + * + * \sa computeScalingRotation(), computeUnitaryPositive() + */ +template<typename MatrixType> +template<typename RotationType, typename ScalingType> +void SVD<MatrixType>::computeRotationScaling(RotationType *rotation, ScalingType *scaling) const +{ + ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices"); + Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1 + Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma); + sv.coeffRef(0) *= x; + if(scaling) scaling->lazyAssign(m_matV * sv.asDiagonal() * m_matV.adjoint()); + if(rotation) + { + MatrixType m(m_matU); + m.col(0) /= x; + rotation->lazyAssign(m * m_matV.adjoint()); + } +} + +/** decomposes the matrix as a product scaling x rotation, the scaling being + * not necessarily positive. + * + * If either pointer is zero, the corresponding computation is skipped. + * + * This method requires the Geometry module. + * + * \sa computeRotationScaling(), computeUnitaryPositive() + */ +template<typename MatrixType> +template<typename ScalingType, typename RotationType> +void SVD<MatrixType>::computeScalingRotation(ScalingType *scaling, RotationType *rotation) const +{ + ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices"); + Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1 + Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma); + sv.coeffRef(0) *= x; + if(scaling) scaling->lazyAssign(m_matU * sv.asDiagonal() * m_matU.adjoint()); + if(rotation) + { + MatrixType m(m_matU); + m.col(0) /= x; + rotation->lazyAssign(m * m_matV.adjoint()); + } +} + + +/** \svd_module + * \returns the SVD decomposition of \c *this + */ +template<typename Derived> +inline SVD<typename MatrixBase<Derived>::PlainObject> +MatrixBase<Derived>::svd() const +{ + return SVD<PlainObject>(derived()); +} + +#endif // EIGEN_SVD_H diff --git a/Eigen/src/LU/PartialPivLU.h b/Eigen/src/LU/PartialPivLU.h index f9e645ec1..2533a3874 100644 --- a/Eigen/src/LU/PartialPivLU.h +++ b/Eigen/src/LU/PartialPivLU.h @@ -489,6 +489,7 @@ MatrixBase<Derived>::partialPivLu() const return PartialPivLU<PlainObject>(eval()); } +#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS /** \lu_module * * Synonym of partialPivLu(). @@ -503,5 +504,6 @@ MatrixBase<Derived>::lu() const { return PartialPivLU<PlainObject>(eval()); } +#endif #endif // EIGEN_PARTIALLU_H diff --git a/Eigen/src/SVD/UpperBidiagonalization.h b/Eigen/src/SVD/UpperBidiagonalization.h index eef92fcbe..2de197da9 100644 --- a/Eigen/src/SVD/UpperBidiagonalization.h +++ b/Eigen/src/SVD/UpperBidiagonalization.h @@ -49,7 +49,7 @@ template<typename _MatrixType> class UpperBidiagonalization typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType; typedef HouseholderSequence< const MatrixType, - CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, Diagonal<const MatrixType,0> > + CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Diagonal<const MatrixType,0> > > HouseholderUSequenceType; typedef HouseholderSequence< const MatrixType, diff --git a/Eigen/src/Sparse/SparseDiagonalProduct.h b/Eigen/src/Sparse/SparseDiagonalProduct.h index 994bf163e..fb9a29c05 100644 --- a/Eigen/src/Sparse/SparseDiagonalProduct.h +++ b/Eigen/src/Sparse/SparseDiagonalProduct.h @@ -115,9 +115,9 @@ namespace internal { template<typename Lhs, typename Rhs, typename SparseDiagonalProductType> class sparse_diagonal_product_inner_iterator_selector <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor> - : public CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator + : public CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator { - typedef typename CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator Base; + typedef typename CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator Base; typedef typename Lhs::Index Index; public: inline sparse_diagonal_product_inner_iterator_selector( @@ -149,9 +149,9 @@ class sparse_diagonal_product_inner_iterator_selector template<typename Lhs, typename Rhs, typename SparseDiagonalProductType> class sparse_diagonal_product_inner_iterator_selector <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal> - : public CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator + : public CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator { - typedef typename CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator Base; + typedef typename CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator Base; typedef typename Lhs::Index Index; public: inline sparse_diagonal_product_inner_iterator_selector( |