Add sub/super-diagonal expression (read/write) as a trivial extension of

DiagonalCoeffs. The current API is simply:
  m.diagonal<1>() => 1st super diagonal
  m.diagonal<-2>() => the 2nd sub diagonal
I'll add a code snippet once we agree on this API.
This commit is contained in:
Gael Guennebaud 2009-02-05 18:37:21 +00:00
parent 9637af5ecf
commit 910b387438
5 changed files with 60 additions and 12 deletions

View File

@ -39,16 +39,17 @@
* *
* \sa MatrixBase::diagonal() * \sa MatrixBase::diagonal()
*/ */
template<typename MatrixType> template<typename MatrixType, int DiagId>
struct ei_traits<DiagonalCoeffs<MatrixType> > struct ei_traits<DiagonalCoeffs<MatrixType,DiagId> >
{ {
typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::Scalar Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested; typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested; typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum { enum {
AbsDiagId = DiagId<0 ? -DiagId : DiagId,
RowsAtCompileTime = int(MatrixType::SizeAtCompileTime) == Dynamic ? Dynamic RowsAtCompileTime = int(MatrixType::SizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime, : EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,
MatrixType::ColsAtCompileTime), MatrixType::ColsAtCompileTime) - AbsDiagId,
ColsAtCompileTime = 1, ColsAtCompileTime = 1,
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime, : EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime,
@ -59,9 +60,14 @@ struct ei_traits<DiagonalCoeffs<MatrixType> >
}; };
}; };
template<typename MatrixType> class DiagonalCoeffs template<typename MatrixType, int DiagId> class DiagonalCoeffs
: public MatrixBase<DiagonalCoeffs<MatrixType> > : public MatrixBase<DiagonalCoeffs<MatrixType, DiagId> >
{ {
enum {
AbsDiagId = DiagId<0 ? -DiagId : DiagId,
OffsetRow = DiagId<0 ? -DiagId : 0,
OffsetCol = DiagId<0 ? 0 : DiagId
};
public: public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalCoeffs) EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalCoeffs)
@ -70,27 +76,27 @@ template<typename MatrixType> class DiagonalCoeffs
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(DiagonalCoeffs) EIGEN_INHERIT_ASSIGNMENT_OPERATORS(DiagonalCoeffs)
inline int rows() const { return std::min(m_matrix.rows(), m_matrix.cols()); } inline int rows() const { return std::min(m_matrix.rows(), m_matrix.cols()) - AbsDiagId; }
inline int cols() const { return 1; } inline int cols() const { return 1; }
inline Scalar& coeffRef(int row, int) inline Scalar& coeffRef(int row, int)
{ {
return m_matrix.const_cast_derived().coeffRef(row, row); return m_matrix.const_cast_derived().coeffRef(row+OffsetRow, row+OffsetCol);
} }
inline const Scalar coeff(int row, int) const inline const Scalar coeff(int row, int) const
{ {
return m_matrix.coeff(row, row); return m_matrix.coeff(row+OffsetRow, row+OffsetCol);
} }
inline Scalar& coeffRef(int index) inline Scalar& coeffRef(int index)
{ {
return m_matrix.const_cast_derived().coeffRef(index, index); return m_matrix.const_cast_derived().coeffRef(index+OffsetRow, index+OffsetCol);
} }
inline const Scalar coeff(int index) const inline const Scalar coeff(int index) const
{ {
return m_matrix.coeff(index, index); return m_matrix.coeff(index+OffsetRow, index+OffsetCol);
} }
protected: protected:
@ -121,4 +127,29 @@ MatrixBase<Derived>::diagonal() const
return DiagonalCoeffs<Derived>(derived()); return DiagonalCoeffs<Derived>(derived());
} }
/** \returns an expression of the \a Id-th sub or super diagonal of the matrix \c *this
*
* \c *this is not required to be square.
*
* The template parameter \a Id represent a super diagonal if \a Id > 0
* and a sub diagonal otherwise. \a Id == 0 is equivalent to the main diagonal.
*
* \sa class DiagonalCoeffs */
template<typename Derived>
template<int Id>
inline DiagonalCoeffs<Derived,Id>
MatrixBase<Derived>::diagonal()
{
return DiagonalCoeffs<Derived,Id>(derived());
}
/** This is the const version of diagonal<int>(). */
template<typename Derived>
template<int Id>
inline const DiagonalCoeffs<Derived,Id>
MatrixBase<Derived>::diagonal() const
{
return DiagonalCoeffs<Derived,Id>(derived());
}
#endif // EIGEN_DIAGONALCOEFFS_H #endif // EIGEN_DIAGONALCOEFFS_H

View File

@ -408,6 +408,9 @@ template<typename Derived> class MatrixBase
DiagonalCoeffs<Derived> diagonal(); DiagonalCoeffs<Derived> diagonal();
const DiagonalCoeffs<Derived> diagonal() const; const DiagonalCoeffs<Derived> diagonal() const;
template<int Id> DiagonalCoeffs<Derived,Id> diagonal();
template<int Id> const DiagonalCoeffs<Derived,Id> diagonal() const;
template<unsigned int Mode> Part<Derived, Mode> part(); template<unsigned int Mode> Part<Derived, Mode> part();
template<unsigned int Mode> const Part<Derived, Mode> part() const; template<unsigned int Mode> const Part<Derived, Mode> part() const;

View File

@ -48,7 +48,7 @@ template<typename Lhs, typename Rhs, int ProductMode> class Product;
template<typename CoeffsVectorType, typename Derived> class DiagonalMatrixBase; template<typename CoeffsVectorType, typename Derived> class DiagonalMatrixBase;
template<typename CoeffsVectorType> class DiagonalMatrixWrapper; template<typename CoeffsVectorType> class DiagonalMatrixWrapper;
template<typename _Scalar, int _Size> class DiagonalMatrix; template<typename _Scalar, int _Size> class DiagonalMatrix;
template<typename MatrixType> class DiagonalCoeffs; template<typename MatrixType, int DiagId=0> class DiagonalCoeffs;
template<typename MatrixType, int PacketAccess = AsRequested> class Map; template<typename MatrixType, int PacketAccess = AsRequested> class Map;
template<typename MatrixType, unsigned int Mode> class Part; template<typename MatrixType, unsigned int Mode> class Part;
template<typename MatrixType, unsigned int Mode> class Extract; template<typename MatrixType, unsigned int Mode> class Extract;

View File

@ -41,7 +41,7 @@
// because extra memory must be allocated for bookkeeping). // because extra memory must be allocated for bookkeeping).
// if the compiler is not GNUC, just cross fingers that the architecture isn't too exotic, because we don't want // if the compiler is not GNUC, just cross fingers that the architecture isn't too exotic, because we don't want
// to keep track of all the different preprocessor symbols for all compilers. // to keep track of all the different preprocessor symbols for all compilers.
#if !defined(__GNUC__) || defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ia64__) #if (!defined(__GNUC__)) || defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ia64__)
#define EIGEN_ARCH_WANTS_ALIGNMENT 1 #define EIGEN_ARCH_WANTS_ALIGNMENT 1
#else #else
#ifdef EIGEN_VECTORIZE #ifdef EIGEN_VECTORIZE

View File

@ -138,6 +138,20 @@ template<typename MatrixType> void submatrices(const MatrixType& m)
VERIFY_IS_APPROX(v1.template end<2>(), v1.template segment<2>(i)); VERIFY_IS_APPROX(v1.template end<2>(), v1.template segment<2>(i));
i = ei_random(0,rows-2); i = ei_random(0,rows-2);
VERIFY_IS_APPROX(v1.segment(i,2), v1.template segment<2>(i)); VERIFY_IS_APPROX(v1.segment(i,2), v1.template segment<2>(i));
enum {
N1 = MatrixType::RowsAtCompileTime>1 ? 1 : 0,
N2 = MatrixType::RowsAtCompileTime>2 ? -2 : 0
};
// check sub/super diagonal
m2.template diagonal<N1>() = 2 * m1.template diagonal<N1>();
m2.template diagonal<N1>()[0] *= 3;
VERIFY_IS_APPROX(m2.template diagonal<N1>()[0], static_cast<Scalar>(6) * m1.template diagonal<N1>()[0]);
m2.template diagonal<N2>() = 2 * m1.template diagonal<N2>();
m2.template diagonal<N2>()[0] *= 3;
VERIFY_IS_APPROX(m2.template diagonal<N2>()[0], static_cast<Scalar>(6) * m1.template diagonal<N2>()[0]);
} }
// stress some basic stuffs with block matrices // stress some basic stuffs with block matrices