00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H
00011 #define EIGEN_SPARSE_SELFADJOINTVIEW_H
00012
00013 namespace Eigen {
00014
00029 template<typename Lhs, typename Rhs, int UpLo>
00030 class SparseSelfAdjointTimeDenseProduct;
00031
00032 template<typename Lhs, typename Rhs, int UpLo>
00033 class DenseTimeSparseSelfAdjointProduct;
00034
00035 namespace internal {
00036
00037 template<typename MatrixType, unsigned int UpLo>
00038 struct traits<SparseSelfAdjointView<MatrixType,UpLo> > : traits<MatrixType> {
00039 };
00040
00041 template<int SrcUpLo,int DstUpLo,typename MatrixType,int DestOrder>
00042 void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
00043
00044 template<int UpLo,typename MatrixType,int DestOrder>
00045 void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
00046
00047 }
00048
00049 template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
00050 : public EigenBase<SparseSelfAdjointView<MatrixType,UpLo> >
00051 {
00052 public:
00053
00054 typedef typename MatrixType::Scalar Scalar;
00055 typedef typename MatrixType::Index Index;
00056 typedef Matrix<Index,Dynamic,1> VectorI;
00057 typedef typename MatrixType::Nested MatrixTypeNested;
00058 typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
00059
00060 inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
00061 {
00062 eigen_assert(rows()==cols() && "SelfAdjointView is only for squared matrices");
00063 }
00064
00065 inline Index rows() const { return m_matrix.rows(); }
00066 inline Index cols() const { return m_matrix.cols(); }
00067
00069 const _MatrixTypeNested& matrix() const { return m_matrix; }
00070 _MatrixTypeNested& matrix() { return m_matrix.const_cast_derived(); }
00071
00073 template<typename OtherDerived>
00074 SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>
00075 operator*(const MatrixBase<OtherDerived>& rhs) const
00076 {
00077 return SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>(m_matrix, rhs.derived());
00078 }
00079
00081 template<typename OtherDerived> friend
00082 DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>
00083 operator*(const MatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
00084 {
00085 return DenseTimeSparseSelfAdjointProduct<OtherDerived,_MatrixTypeNested,UpLo>(lhs.derived(), rhs.m_matrix);
00086 }
00087
00096 template<typename DerivedU>
00097 SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
00098
00100 template<typename DestScalar,int StorageOrder> void evalTo(SparseMatrix<DestScalar,StorageOrder,Index>& _dest) const
00101 {
00102 internal::permute_symm_to_fullsymm<UpLo>(m_matrix, _dest);
00103 }
00104
00105 template<typename DestScalar> void evalTo(DynamicSparseMatrix<DestScalar,ColMajor,Index>& _dest) const
00106 {
00107
00108 SparseMatrix<DestScalar,ColMajor,Index> tmp(_dest.rows(),_dest.cols());
00109 internal::permute_symm_to_fullsymm<UpLo>(m_matrix, tmp);
00110 _dest = tmp;
00111 }
00112
00114 SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix<Dynamic,Dynamic,Index>& perm) const
00115 {
00116 return SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo>(m_matrix, perm);
00117 }
00118
00119 template<typename SrcMatrixType,int SrcUpLo>
00120 SparseSelfAdjointView& operator=(const SparseSymmetricPermutationProduct<SrcMatrixType,SrcUpLo>& permutedMatrix)
00121 {
00122 permutedMatrix.evalTo(*this);
00123 return *this;
00124 }
00125
00126
00127 SparseSelfAdjointView& operator=(const SparseSelfAdjointView& src)
00128 {
00129 PermutationMatrix<Dynamic> pnull;
00130 return *this = src.twistedBy(pnull);
00131 }
00132
00133 template<typename SrcMatrixType,unsigned int SrcUpLo>
00134 SparseSelfAdjointView& operator=(const SparseSelfAdjointView<SrcMatrixType,SrcUpLo>& src)
00135 {
00136 PermutationMatrix<Dynamic> pnull;
00137 return *this = src.twistedBy(pnull);
00138 }
00139
00140
00141
00142
00143
00144 protected:
00145
00146 typename MatrixType::Nested m_matrix;
00147 mutable VectorI m_countPerRow;
00148 mutable VectorI m_countPerCol;
00149 };
00150
00151
00152
00153
00154
00155 template<typename Derived>
00156 template<unsigned int UpLo>
00157 const SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView() const
00158 {
00159 return derived();
00160 }
00161
00162 template<typename Derived>
00163 template<unsigned int UpLo>
00164 SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView()
00165 {
00166 return derived();
00167 }
00168
00169
00170
00171
00172
00173 template<typename MatrixType, unsigned int UpLo>
00174 template<typename DerivedU>
00175 SparseSelfAdjointView<MatrixType,UpLo>&
00176 SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha)
00177 {
00178 SparseMatrix<Scalar,MatrixType::Flags&RowMajorBit?RowMajor:ColMajor> tmp = u * u.adjoint();
00179 if(alpha==Scalar(0))
00180 m_matrix.const_cast_derived() = tmp.template triangularView<UpLo>();
00181 else
00182 m_matrix.const_cast_derived() += alpha * tmp.template triangularView<UpLo>();
00183
00184 return *this;
00185 }
00186
00187
00188
00189
00190
00191 namespace internal {
00192 template<typename Lhs, typename Rhs, int UpLo>
00193 struct traits<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo> >
00194 : traits<ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
00195 {
00196 typedef Dense StorageKind;
00197 };
00198 }
00199
00200 template<typename Lhs, typename Rhs, int UpLo>
00201 class SparseSelfAdjointTimeDenseProduct
00202 : public ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
00203 {
00204 public:
00205 EIGEN_PRODUCT_PUBLIC_INTERFACE(SparseSelfAdjointTimeDenseProduct)
00206
00207 SparseSelfAdjointTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00208 {}
00209
00210 template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
00211 {
00212 EIGEN_ONLY_USED_FOR_DEBUG(alpha);
00213
00214 eigen_assert(alpha==Scalar(1) && "alpha != 1 is not implemented yet, sorry");
00215 typedef typename internal::remove_all<Lhs>::type _Lhs;
00216 typedef typename internal::remove_all<Rhs>::type _Rhs;
00217 typedef typename _Lhs::InnerIterator LhsInnerIterator;
00218 enum {
00219 LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
00220 ProcessFirstHalf =
00221 ((UpLo&(Upper|Lower))==(Upper|Lower))
00222 || ( (UpLo&Upper) && !LhsIsRowMajor)
00223 || ( (UpLo&Lower) && LhsIsRowMajor),
00224 ProcessSecondHalf = !ProcessFirstHalf
00225 };
00226 for (Index j=0; j<m_lhs.outerSize(); ++j)
00227 {
00228 LhsInnerIterator i(m_lhs,j);
00229 if (ProcessSecondHalf)
00230 {
00231 while (i && i.index()<j) ++i;
00232 if(i && i.index()==j)
00233 {
00234 dest.row(j) += i.value() * m_rhs.row(j);
00235 ++i;
00236 }
00237 }
00238 for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i)
00239 {
00240 Index a = LhsIsRowMajor ? j : i.index();
00241 Index b = LhsIsRowMajor ? i.index() : j;
00242 typename Lhs::Scalar v = i.value();
00243 dest.row(a) += (v) * m_rhs.row(b);
00244 dest.row(b) += internal::conj(v) * m_rhs.row(a);
00245 }
00246 if (ProcessFirstHalf && i && (i.index()==j))
00247 dest.row(j) += i.value() * m_rhs.row(j);
00248 }
00249 }
00250
00251 private:
00252 SparseSelfAdjointTimeDenseProduct& operator=(const SparseSelfAdjointTimeDenseProduct&);
00253 };
00254
00255 namespace internal {
00256 template<typename Lhs, typename Rhs, int UpLo>
00257 struct traits<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo> >
00258 : traits<ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
00259 {};
00260 }
00261
00262 template<typename Lhs, typename Rhs, int UpLo>
00263 class DenseTimeSparseSelfAdjointProduct
00264 : public ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
00265 {
00266 public:
00267 EIGEN_PRODUCT_PUBLIC_INTERFACE(DenseTimeSparseSelfAdjointProduct)
00268
00269 DenseTimeSparseSelfAdjointProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00270 {}
00271
00272 template<typename Dest> void scaleAndAddTo(Dest& , Scalar ) const
00273 {
00274
00275 }
00276
00277 private:
00278 DenseTimeSparseSelfAdjointProduct& operator=(const DenseTimeSparseSelfAdjointProduct&);
00279 };
00280
00281
00282
00283
00284 namespace internal {
00285
00286 template<typename MatrixType, int UpLo>
00287 struct traits<SparseSymmetricPermutationProduct<MatrixType,UpLo> > : traits<MatrixType> {
00288 };
00289
00290 template<int UpLo,typename MatrixType,int DestOrder>
00291 void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
00292 {
00293 typedef typename MatrixType::Index Index;
00294 typedef typename MatrixType::Scalar Scalar;
00295 typedef SparseMatrix<Scalar,DestOrder,Index> Dest;
00296 typedef Matrix<Index,Dynamic,1> VectorI;
00297
00298 Dest& dest(_dest.derived());
00299 enum {
00300 StorageOrderMatch = int(Dest::IsRowMajor) == int(MatrixType::IsRowMajor)
00301 };
00302
00303 Index size = mat.rows();
00304 VectorI count;
00305 count.resize(size);
00306 count.setZero();
00307 dest.resize(size,size);
00308 for(Index j = 0; j<size; ++j)
00309 {
00310 Index jp = perm ? perm[j] : j;
00311 for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
00312 {
00313 Index i = it.index();
00314 Index r = it.row();
00315 Index c = it.col();
00316 Index ip = perm ? perm[i] : i;
00317 if(UpLo==(Upper|Lower))
00318 count[StorageOrderMatch ? jp : ip]++;
00319 else if(r==c)
00320 count[ip]++;
00321 else if(( UpLo==Lower && r>c) || ( UpLo==Upper && r<c))
00322 {
00323 count[ip]++;
00324 count[jp]++;
00325 }
00326 }
00327 }
00328 Index nnz = count.sum();
00329
00330
00331 dest.resizeNonZeros(nnz);
00332 dest.outerIndexPtr()[0] = 0;
00333 for(Index j=0; j<size; ++j)
00334 dest.outerIndexPtr()[j+1] = dest.outerIndexPtr()[j] + count[j];
00335 for(Index j=0; j<size; ++j)
00336 count[j] = dest.outerIndexPtr()[j];
00337
00338
00339 for(Index j = 0; j<size; ++j)
00340 {
00341 for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
00342 {
00343 Index i = it.index();
00344 Index r = it.row();
00345 Index c = it.col();
00346
00347 Index jp = perm ? perm[j] : j;
00348 Index ip = perm ? perm[i] : i;
00349
00350 if(UpLo==(Upper|Lower))
00351 {
00352 Index k = count[StorageOrderMatch ? jp : ip]++;
00353 dest.innerIndexPtr()[k] = StorageOrderMatch ? ip : jp;
00354 dest.valuePtr()[k] = it.value();
00355 }
00356 else if(r==c)
00357 {
00358 Index k = count[ip]++;
00359 dest.innerIndexPtr()[k] = ip;
00360 dest.valuePtr()[k] = it.value();
00361 }
00362 else if(( (UpLo&Lower)==Lower && r>c) || ( (UpLo&Upper)==Upper && r<c))
00363 {
00364 if(!StorageOrderMatch)
00365 std::swap(ip,jp);
00366 Index k = count[jp]++;
00367 dest.innerIndexPtr()[k] = ip;
00368 dest.valuePtr()[k] = it.value();
00369 k = count[ip]++;
00370 dest.innerIndexPtr()[k] = jp;
00371 dest.valuePtr()[k] = internal::conj(it.value());
00372 }
00373 }
00374 }
00375 }
00376
00377 template<int _SrcUpLo,int _DstUpLo,typename MatrixType,int DstOrder>
00378 void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DstOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
00379 {
00380 typedef typename MatrixType::Index Index;
00381 typedef typename MatrixType::Scalar Scalar;
00382 SparseMatrix<Scalar,DstOrder,Index>& dest(_dest.derived());
00383 typedef Matrix<Index,Dynamic,1> VectorI;
00384 enum {
00385 SrcOrder = MatrixType::IsRowMajor ? RowMajor : ColMajor,
00386 StorageOrderMatch = int(SrcOrder) == int(DstOrder),
00387 DstUpLo = DstOrder==RowMajor ? (_DstUpLo==Upper ? Lower : Upper) : _DstUpLo,
00388 SrcUpLo = SrcOrder==RowMajor ? (_SrcUpLo==Upper ? Lower : Upper) : _SrcUpLo
00389 };
00390
00391 Index size = mat.rows();
00392 VectorI count(size);
00393 count.setZero();
00394 dest.resize(size,size);
00395 for(Index j = 0; j<size; ++j)
00396 {
00397 Index jp = perm ? perm[j] : j;
00398 for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
00399 {
00400 Index i = it.index();
00401 if((int(SrcUpLo)==int(Lower) && i<j) || (int(SrcUpLo)==int(Upper) && i>j))
00402 continue;
00403
00404 Index ip = perm ? perm[i] : i;
00405 count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
00406 }
00407 }
00408 dest.outerIndexPtr()[0] = 0;
00409 for(Index j=0; j<size; ++j)
00410 dest.outerIndexPtr()[j+1] = dest.outerIndexPtr()[j] + count[j];
00411 dest.resizeNonZeros(dest.outerIndexPtr()[size]);
00412 for(Index j=0; j<size; ++j)
00413 count[j] = dest.outerIndexPtr()[j];
00414
00415 for(Index j = 0; j<size; ++j)
00416 {
00417
00418 for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
00419 {
00420 Index i = it.index();
00421 if((int(SrcUpLo)==int(Lower) && i<j) || (int(SrcUpLo)==int(Upper) && i>j))
00422 continue;
00423
00424 Index jp = perm ? perm[j] : j;
00425 Index ip = perm? perm[i] : i;
00426
00427 Index k = count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
00428 dest.innerIndexPtr()[k] = int(DstUpLo)==int(Lower) ? (std::max)(ip,jp) : (std::min)(ip,jp);
00429
00430 if(!StorageOrderMatch) std::swap(ip,jp);
00431 if( ((int(DstUpLo)==int(Lower) && ip<jp) || (int(DstUpLo)==int(Upper) && ip>jp)))
00432 dest.valuePtr()[k] = conj(it.value());
00433 else
00434 dest.valuePtr()[k] = it.value();
00435 }
00436 }
00437 }
00438
00439 }
00440
00441 template<typename MatrixType,int UpLo>
00442 class SparseSymmetricPermutationProduct
00443 : public EigenBase<SparseSymmetricPermutationProduct<MatrixType,UpLo> >
00444 {
00445 public:
00446 typedef typename MatrixType::Scalar Scalar;
00447 typedef typename MatrixType::Index Index;
00448 protected:
00449 typedef PermutationMatrix<Dynamic,Dynamic,Index> Perm;
00450 public:
00451 typedef Matrix<Index,Dynamic,1> VectorI;
00452 typedef typename MatrixType::Nested MatrixTypeNested;
00453 typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
00454
00455 SparseSymmetricPermutationProduct(const MatrixType& mat, const Perm& perm)
00456 : m_matrix(mat), m_perm(perm)
00457 {}
00458
00459 inline Index rows() const { return m_matrix.rows(); }
00460 inline Index cols() const { return m_matrix.cols(); }
00461
00462 template<typename DestScalar, int Options, typename DstIndex>
00463 void evalTo(SparseMatrix<DestScalar,Options,DstIndex>& _dest) const
00464 {
00465 internal::permute_symm_to_fullsymm<UpLo>(m_matrix,_dest,m_perm.indices().data());
00466 }
00467
00468 template<typename DestType,unsigned int DestUpLo> void evalTo(SparseSelfAdjointView<DestType,DestUpLo>& dest) const
00469 {
00470 internal::permute_symm_to_symm<UpLo,DestUpLo>(m_matrix,dest.matrix(),m_perm.indices().data());
00471 }
00472
00473 protected:
00474 MatrixTypeNested m_matrix;
00475 const Perm& m_perm;
00476
00477 };
00478
00479 }
00480
00481 #endif // EIGEN_SPARSE_SELFADJOINTVIEW_H