From 08e419dcb151da41f169304f751e5467cf0c7b4a Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 4 Jul 2009 11:16:27 +0200 Subject: * update sparse module wrt new diagonal matrix impl * fix a bug is SparseMatrix --- Eigen/src/Core/DiagonalMatrix.h | 6 +++- Eigen/src/Core/util/Constants.h | 12 +------- Eigen/src/Core/util/Meta.h | 12 +++++++- Eigen/src/Sparse/SparseDiagonalProduct.h | 52 +++++++++++++++++++++++--------- Eigen/src/Sparse/SparseMatrix.h | 2 +- Eigen/src/Sparse/SparseMatrixBase.h | 17 ++++++++++- Eigen/src/Sparse/SparseProduct.h | 17 ++--------- test/sparse_product.cpp | 1 - 8 files changed, 75 insertions(+), 44 deletions(-) diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 413ad5c9f..a092b7794 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -38,7 +38,8 @@ class DiagonalBase : public MultiplierBase ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, - IsVectorAtCompileTime = 0 + IsVectorAtCompileTime = 0, + Flags = 0 }; typedef Matrix DenseMatrixType; @@ -52,6 +53,9 @@ class DiagonalBase : public MultiplierBase inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); } inline DiagonalVectorType& diagonal() { return derived().diagonal(); } + + inline int rows() const { return diagonal().size(); } + inline int cols() const { return diagonal().size(); } template const DiagonalProduct diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 35e4767b8..454b44e52 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // // Eigen is free software; you can redistribute it and/or @@ -185,9 +185,6 @@ const unsigned int HereditaryBits = RowMajorBit | EvalBeforeNestingBit | EvalBeforeAssigningBit | SparseBit; - -// diagonal means both upper and lower triangular -const unsigned DiagonalBits = UpperTriangularBit | LowerTriangularBit; // Possible values for the Mode parameter of part() const unsigned int UpperTriangular = UpperTriangularBit; @@ -198,13 +195,6 @@ const unsigned int SelfAdjoint = SelfAdjointBit; const unsigned int UnitUpperTriangular = UpperTriangularBit | UnitDiagBit; const unsigned int UnitLowerTriangular = LowerTriangularBit | UnitDiagBit; -template struct ei_is_diagonal -{ - enum { - ret = ( (unsigned int)(T::Flags) & DiagonalBits ) == DiagonalBits - }; -}; - enum { DiagonalOnTheLeft, DiagonalOnTheRight }; enum { Aligned, Unaligned }; diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index 7552dd70c..2f5363275 100644 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // // Eigen is free software; you can redistribute it and/or @@ -186,6 +186,16 @@ struct ei_result_of(ArgType0,ArgType1)> { typedef typename ei_scalar_product_traits::type, typename ei_cleantype::type>::ReturnType type; }; +template struct ei_is_diagonal +{ enum { ret = false }; }; +template struct ei_is_diagonal > +{ enum { ret = true }; }; + +template struct ei_is_diagonal > +{ enum { ret = true }; }; + +template struct ei_is_diagonal > +{ enum { ret = true }; }; #endif // EIGEN_META_H diff --git a/Eigen/src/Sparse/SparseDiagonalProduct.h b/Eigen/src/Sparse/SparseDiagonalProduct.h index 3a148b09e..5fb149a2c 100644 --- a/Eigen/src/Sparse/SparseDiagonalProduct.h +++ b/Eigen/src/Sparse/SparseDiagonalProduct.h @@ -25,8 +25,9 @@ #ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H #define EIGEN_SPARSE_DIAGONAL_PRODUCT_H -// the product a diagonal matrix with a sparse matrix can be easily -// implemented using expression template. We have two very different cases: +// The product of a diagonal matrix with a sparse matrix can be easily +// implemented using expression template. +// We have two consider very different cases: // 1 - diag * row-major sparse // => each inner vector <=> scalar * sparse vector product // => so we can reuse CwiseUnaryOp::InnerIterator @@ -37,13 +38,21 @@ // The two other cases are symmetric. template -struct ei_traits > : ei_traits > +struct ei_traits > { typedef typename ei_cleantype::type _Lhs; typedef typename ei_cleantype::type _Rhs; + typedef typename _Lhs::Scalar Scalar; enum { + RowsAtCompileTime = _Lhs::RowsAtCompileTime, + ColsAtCompileTime = _Rhs::ColsAtCompileTime, + + MaxRowsAtCompileTime = _Lhs::MaxRowsAtCompileTime, + MaxColsAtCompileTime = _Rhs::MaxColsAtCompileTime, + SparseFlags = ei_is_diagonal<_Lhs>::ret ? int(_Rhs::Flags) : int(_Lhs::Flags), - Flags = SparseBit | (SparseFlags&RowMajorBit) + Flags = SparseBit | (SparseFlags&RowMajorBit), + CoeffReadCost = Dynamic }; }; @@ -51,11 +60,16 @@ enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor}; template class ei_sparse_diagonal_product_inner_iterator_selector; -template -class SparseDiagonalProduct : public SparseMatrixBase >, ei_no_assignment_operator +template +class SparseDiagonalProduct + : public SparseMatrixBase >, + ei_no_assignment_operator { - typedef typename ei_traits::_LhsNested _LhsNested; - typedef typename ei_traits::_RhsNested _RhsNested; + typedef typename Lhs::Nested LhsNested; + typedef typename Rhs::Nested RhsNested; + + typedef typename ei_cleantype::type _LhsNested; + typedef typename ei_cleantype::type _RhsNested; enum { LhsMode = ei_is_diagonal<_LhsNested>::ret ? SDP_IsDiagonal @@ -71,8 +85,8 @@ class SparseDiagonalProduct : public SparseMatrixBase InnerIterator; - template - EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs) + template + EIGEN_STRONG_INLINE SparseDiagonalProduct(const _Lhs& lhs, const _Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) { ei_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product"); @@ -109,12 +123,12 @@ class ei_sparse_diagonal_product_inner_iterator_selector : public SparseCwiseBinaryOp< ei_scalar_product_op, SparseInnerVectorSet, - typename Lhs::_CoeffsVectorType>::InnerIterator + typename Lhs::DiagonalVectorType>::InnerIterator { typedef typename SparseCwiseBinaryOp< ei_scalar_product_op, SparseInnerVectorSet, - typename Lhs::_CoeffsVectorType>::InnerIterator Base; + typename Lhs::DiagonalVectorType>::InnerIterator Base; public: inline ei_sparse_diagonal_product_inner_iterator_selector( const SparseDiagonalProductType& expr, int outer) @@ -141,12 +155,12 @@ class ei_sparse_diagonal_product_inner_iterator_selector : public SparseCwiseBinaryOp< ei_scalar_product_op, SparseInnerVectorSet, - NestByValue > >::InnerIterator + NestByValue > >::InnerIterator { typedef typename SparseCwiseBinaryOp< ei_scalar_product_op, SparseInnerVectorSet, - NestByValue > >::InnerIterator Base; + NestByValue > >::InnerIterator Base; public: inline ei_sparse_diagonal_product_inner_iterator_selector( const SparseDiagonalProductType& expr, int outer) @@ -154,4 +168,14 @@ class ei_sparse_diagonal_product_inner_iterator_selector {} }; +// SparseMatrixBase functions + +template +template +const SparseDiagonalProduct +SparseMatrixBase::operator*(const DiagonalBase &other) const +{ + return SparseDiagonalProduct(this->derived(), other.derived()); +} + #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index 03bc60bb5..b751b5cb9 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -371,7 +371,7 @@ class SparseMatrix const int outerSize = IsRowMajor ? rows : cols; m_innerSize = IsRowMajor ? cols : rows; m_data.clear(); - if (m_outerSize != outerSize) + if (m_outerSize != outerSize || m_outerSize==0) { delete[] m_outerIndex; m_outerIndex = new int [outerSize+1]; diff --git a/Eigen/src/Sparse/SparseMatrixBase.h b/Eigen/src/Sparse/SparseMatrixBase.h index 8d9406cfb..8c53757b0 100644 --- a/Eigen/src/Sparse/SparseMatrixBase.h +++ b/Eigen/src/Sparse/SparseMatrixBase.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2009 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -37,6 +37,9 @@ * */ template class SparseMatrixBase +#ifndef EIGEN_PARSED_BY_DOXYGEN + : public MultiplierBase +#endif // not EIGEN_PARSED_BY_DOXYGEN { public: @@ -301,10 +304,22 @@ template class SparseMatrixBase { return matrix*scalar; } + // sparse * sparse template const typename SparseProductReturnType::Type operator*(const SparseMatrixBase &other) const; + // sparse * diagonal + template + const SparseDiagonalProduct + operator*(const DiagonalBase &other) const; + + // diagonal * sparse + template friend + const SparseDiagonalProduct + operator*(const DiagonalBase &lhs, const SparseMatrixBase& rhs) + { return SparseDiagonalProduct(lhs.derived(), rhs.derived()); } + // dense * sparse (return a dense object) template friend const typename SparseProductReturnType::Type diff --git a/Eigen/src/Sparse/SparseProduct.h b/Eigen/src/Sparse/SparseProduct.h index 5222439d8..a9ad8aad4 100644 --- a/Eigen/src/Sparse/SparseProduct.h +++ b/Eigen/src/Sparse/SparseProduct.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2009 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,9 +29,7 @@ template struct ei_sparse_product_mode { enum { - value = ei_is_diagonal::ret || ei_is_diagonal::ret - ? DiagonalProduct - : (Rhs::Flags&Lhs::Flags&SparseBit)==SparseBit + value = (Rhs::Flags&Lhs::Flags&SparseBit)==SparseBit ? SparseTimeSparseProduct : (Lhs::Flags&SparseBit)==SparseBit ? SparseTimeDenseProduct @@ -47,15 +45,6 @@ struct SparseProductReturnType typedef SparseProduct Type; }; -template -struct SparseProductReturnType -{ - typedef const typename ei_nested::type LhsNested; - typedef const typename ei_nested::type RhsNested; - - typedef SparseDiagonalProduct Type; -}; - // sparse product return type specialization template struct SparseProductReturnType @@ -106,7 +95,7 @@ struct ei_traits > // RhsIsRowMajor = (RhsFlags & RowMajorBit)==RowMajorBit, EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit), - ResultIsSparse = ProductMode==SparseTimeSparseProduct || ProductMode==DiagonalProduct, + ResultIsSparse = ProductMode==SparseTimeSparseProduct, RemovedBits = ~( (EvalToRowMajor ? 0 : RowMajorBit) | (ResultIsSparse ? 0 : SparseBit) ), diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp index 122fd4325..743273f65 100644 --- a/test/sparse_product.cpp +++ b/test/sparse_product.cpp @@ -118,7 +118,6 @@ template void sparse_product(const SparseMatrixType& VERIFY_IS_APPROX(x=mLo.template marked()*b, refX=refS*b); VERIFY_IS_APPROX(x=mS.template marked()*b, refX=refS*b); } - } void test_sparse_product() -- cgit v1.2.3