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()
*/
template<typename MatrixType>
struct ei_traits<DiagonalCoeffs<MatrixType> >
template<typename MatrixType, int DiagId>
struct ei_traits<DiagonalCoeffs<MatrixType,DiagId> >
{
typedef typename MatrixType::Scalar Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
AbsDiagId = DiagId<0 ? -DiagId : DiagId,
RowsAtCompileTime = int(MatrixType::SizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,
MatrixType::ColsAtCompileTime),
MatrixType::ColsAtCompileTime) - AbsDiagId,
ColsAtCompileTime = 1,
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime,
@ -59,9 +60,14 @@ struct ei_traits<DiagonalCoeffs<MatrixType> >
};
};
template<typename MatrixType> class DiagonalCoeffs
: public MatrixBase<DiagonalCoeffs<MatrixType> >
template<typename MatrixType, int DiagId> class DiagonalCoeffs
: public MatrixBase<DiagonalCoeffs<MatrixType, DiagId> >
{
enum {
AbsDiagId = DiagId<0 ? -DiagId : DiagId,
OffsetRow = DiagId<0 ? -DiagId : 0,
OffsetCol = DiagId<0 ? 0 : DiagId
};
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalCoeffs)
@ -70,27 +76,27 @@ template<typename MatrixType> class 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 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
{
return m_matrix.coeff(row, row);
return m_matrix.coeff(row+OffsetRow, row+OffsetCol);
}
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
{
return m_matrix.coeff(index, index);
return m_matrix.coeff(index+OffsetRow, index+OffsetCol);
}
protected:
@ -121,4 +127,29 @@ MatrixBase<Derived>::diagonal() const
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

View File

@ -408,6 +408,9 @@ template<typename Derived> class MatrixBase
DiagonalCoeffs<Derived> diagonal();
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> 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> class DiagonalMatrixWrapper;
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, unsigned int Mode> class Part;
template<typename MatrixType, unsigned int Mode> class Extract;

View File

@ -41,7 +41,7 @@
// 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
// 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
#else
#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));
i = ei_random(0,rows-2);
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