// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009 Gael Guennebaud // // 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 . #ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H #define EIGEN_SPARSE_SELFADJOINTVIEW_H /** \class SparseSelfAdjointView * \nonstableyet * * \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix. * * \param MatrixType the type of the dense matrix storing the coefficients * \param UpLo can be either \c Lower or \c Upper * * This class is an expression of a sefladjoint matrix from a triangular part of a matrix * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView() * and most of the time this is the only way that it is used. * * \sa SparseMatrixBase::selfAdjointView() */ template class SparseSelfAdjointTimeDenseProduct; template class DenseTimeSparseSelfAdjointProduct; template class SparseSelfAdjointView { public: typedef typename ei_traits::Scalar Scalar; inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix) { ei_assert(ei_are_flags_consistent::ret); ei_assert(rows()==cols() && "SelfAdjointView is only for squared matrices"); } inline int rows() const { return m_matrix.rows(); } inline int cols() const { return m_matrix.cols(); } /** \internal \returns a reference to the nested matrix */ const MatrixType& matrix() const { return m_matrix; } /** Efficient sparse self-adjoint matrix times dense vector/matrix product */ template SparseSelfAdjointTimeDenseProduct operator*(const MatrixBase& rhs) const { return SparseSelfAdjointTimeDenseProduct(m_matrix, rhs.derived()); } /** Efficient dense vector/matrix times sparse self-adjoint matrix product */ template friend DenseTimeSparseSelfAdjointProduct operator*(const MatrixBase& lhs, const SparseSelfAdjointView& rhs) { return DenseTimeSparseSelfAdjointProduct(lhs.derived(), rhs.m_matrix); } /** Perform a symmetric rank K update of the selfadjoint matrix \c *this: * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix. * * \returns a reference to \c *this * * Note that it is faster to set alpha=0 than initializing the matrix to zero * and then keep the default value alpha=1. * * To perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply * call this function with u.adjoint(). */ template SparseSelfAdjointView& rankUpdate(const MatrixBase& u, Scalar alpha = Scalar(1)); // const SparseLLT llt() const; // const SparseLDLT ldlt() const; protected: const typename MatrixType::Nested m_matrix; }; /*************************************************************************** * Implementation of SparseMatrixBase methods ***************************************************************************/ template template const SparseSelfAdjointView SparseMatrixBase::selfadjointView() const { return derived(); } template template SparseSelfAdjointView SparseMatrixBase::selfadjointView() { return derived(); } /*************************************************************************** * Implementation of SparseSelfAdjointView methods ***************************************************************************/ template template SparseSelfAdjointView& SparseSelfAdjointView::rankUpdate(const MatrixBase& u, Scalar alpha) { SparseMatrix tmp = u * u.adjoint(); if(alpha==Scalar(0)) m_matrix = tmp.template triangularView(); else m_matrix += alpha * tmp.template triangularView(); return this; } /*************************************************************************** * Implementation of sparse self-adjoint time dense matrix ***************************************************************************/ template struct ei_traits > : ei_traits, Lhs, Rhs> > { typedef Dense StorageType; }; template class SparseSelfAdjointTimeDenseProduct : public ProductBase, Lhs, Rhs> { public: EIGEN_PRODUCT_PUBLIC_INTERFACE(SparseSelfAdjointTimeDenseProduct) SparseSelfAdjointTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {} template void scaleAndAddTo(Dest& dest, Scalar alpha) const { // TODO use alpha ei_assert(alpha==Scalar(1) && "alpha != 1 is not implemented yet, sorry"); typedef typename ei_cleantype::type _Lhs; typedef typename ei_cleantype::type _Rhs; typedef typename _Lhs::InnerIterator LhsInnerIterator; enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit, ProcessFirstHalf = ((UpLo&(Upper|Lower))==(Upper|Lower)) || ( (UpLo&Upper) && !LhsIsRowMajor) || ( (UpLo&Lower) && LhsIsRowMajor), ProcessSecondHalf = !ProcessFirstHalf }; for (int j=0; j dest_j(dest.row(LhsIsRowMajor ? j : 0)); for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i) { int a = LhsIsRowMajor ? j : i.index(); int b = LhsIsRowMajor ? i.index() : j; typename Lhs::Scalar v = i.value(); dest.row(a) += (v) * m_rhs.row(b); dest.row(b) += ei_conj(v) * m_rhs.row(a); } if (ProcessFirstHalf && i && (i.index()==j)) dest.row(j) += i.value() * m_rhs.row(j); } } private: SparseSelfAdjointTimeDenseProduct& operator=(const SparseSelfAdjointTimeDenseProduct&); }; template struct ei_traits > : ei_traits, Lhs, Rhs> > {}; template class DenseTimeSparseSelfAdjointProduct : public ProductBase, Lhs, Rhs> { public: EIGEN_PRODUCT_PUBLIC_INTERFACE(DenseTimeSparseSelfAdjointProduct) DenseTimeSparseSelfAdjointProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {} template void scaleAndAddTo(Dest& dest, Scalar alpha) const { // TODO } private: DenseTimeSparseSelfAdjointProduct& operator=(const DenseTimeSparseSelfAdjointProduct&); }; #endif // EIGEN_SPARSE_SELFADJOINTVIEW_H