Big change in DiagonalMatrix and Geometry/Scaling:

* previous DiagonalMatrix expression is now DiagonalMatrixWrapper
* DiagonalMatrix class is now for storage
* add the DiagonalMatrixBase class to factorize code of the
  two previous classes
* remove Scaling class (it is now a global function)
* add UniformScaling helper class
  (don't use it directly, use the Scaling function)
* add the Scaling global function to simplify the creation
  of scaling objects
There is still a lot to do, in particular about DiagonalProduct for which
the goal is to get rid of the "if()" in the coeff() function. At least
it is not worse than before ! Also need to uptade the tutorial and add more doc.
This commit is contained in:
Gael Guennebaud
2009-01-28 16:26:06 +00:00
parent da555585e2
commit 1b194193ef
13 changed files with 439 additions and 237 deletions

View File

@@ -25,22 +25,208 @@
#ifndef EIGEN_DIAGONALMATRIX_H
#define EIGEN_DIAGONALMATRIX_H
template<typename CoeffsVectorType, typename Derived>
class DiagonalMatrixBase : ei_no_assignment_operator,
public MatrixBase<Derived>
{
public:
typedef MatrixBase<Derived> Base;
typedef typename ei_traits<Derived>::Scalar Scalar;
typedef typename Base::PacketScalar PacketScalar;
using Base::derived;
protected:
typedef typename ei_cleantype<CoeffsVectorType>::type _CoeffsVectorType;
/** Default constructor without initialization */
inline DiagonalMatrixBase() {}
/** Constructs a diagonal matrix with given dimension */
inline DiagonalMatrixBase(int dim) : m_coeffs(dim) {}
/** Generic constructor from an expression */
template<typename OtherDerived>
inline DiagonalMatrixBase(const MatrixBase<OtherDerived>& other)
{
construct_from_expression<OtherDerived>::run(derived(),other.derived());
}
template<typename OtherDerived,
bool IsVector = OtherDerived::IsVectorAtCompileTime,
bool IsDiagonal = (OtherDerived::Flags&Diagonal)==Diagonal>
struct construct_from_expression;
// = vector
template<typename OtherDerived>
struct construct_from_expression<OtherDerived,true,false>
{
static void run(Derived& dst, const OtherDerived& src)
{ dst.m_coeffs = src; }
};
// = diagonal
template<typename OtherDerived, bool IsVector>
struct construct_from_expression<OtherDerived,IsVector,true>
{
static void run(Derived& dst, const OtherDerived& src)
{ dst.m_coeffs = src.diagonal(); }
};
public:
inline DiagonalMatrixBase(const _CoeffsVectorType& coeffs) : m_coeffs(coeffs)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_CoeffsVectorType);
ei_assert(coeffs.size() > 0);
}
template<typename OtherDerived, bool IsVector=OtherDerived::IsVectorAtCompileTime>
struct ei_diagonal_product_ctor {
static void run(DiagonalMatrixBase& dst, const OtherDerived& src)
{ dst.m_coeffs = src; }
};
template<typename OtherDerived>
struct ei_diagonal_product_ctor<OtherDerived,false> {
static void run(DiagonalMatrixBase& dst, const OtherDerived& src)
{
EIGEN_STATIC_ASSERT((OtherDerived::Flags&Diagonal)==Diagonal, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX);
dst.m_coeffs = src.diagonal();
}
};
template<typename NewType>
inline DiagonalMatrixWrapper<NestByValue<CwiseUnaryOp<ei_scalar_cast_op<Scalar, NewType>, _CoeffsVectorType> > > cast() const
{
return m_coeffs.template cast<NewType>().nestByValue().asDiagonal();
}
/** Assignment operator.
* The right-hand-side \a other must be either a vector representing the diagonal
* coefficients or a diagonal matrix expression.
*/
template<typename OtherDerived>
inline Derived& operator=(const MatrixBase<OtherDerived>& other)
{
construct_from_expression<OtherDerived>::run(derived(),other);
return derived();
}
inline int rows() const { return m_coeffs.size(); }
inline int cols() const { return m_coeffs.size(); }
inline const Scalar coeff(int row, int col) const
{
return row == col ? m_coeffs.coeff(row) : static_cast<Scalar>(0);
}
inline const Scalar coeffRef(int row, int col) const
{
ei_assert(row==col);
return m_coeffs.coeffRef(row);
}
inline _CoeffsVectorType& diagonal() { return m_coeffs; }
inline const _CoeffsVectorType& diagonal() const { return m_coeffs; }
protected:
CoeffsVectorType m_coeffs;
};
/** \class DiagonalMatrix
* \nonstableyet
* \nonstableyet
*
* \brief Represent a diagonal matrix with its storage
*
* \param _Scalar the type of coefficients
* \param _Size the dimension of the matrix
*
* \sa class Matrix
*/
template<typename _Scalar,int _Size>
struct ei_traits<DiagonalMatrix<_Scalar,_Size> > : ei_traits<Matrix<_Scalar,_Size,_Size> >
{
enum {
Flags = (ei_traits<Matrix<_Scalar,_Size,_Size> >::Flags & HereditaryBits) | Diagonal
};
};
template<typename _Scalar, int _Size>
class DiagonalMatrix
: public DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, DiagonalMatrix<_Scalar,_Size> >
{
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix)
typedef DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, DiagonalMatrix<_Scalar,_Size> > DiagonalBase;
protected:
typedef Matrix<_Scalar,_Size,1> CoeffVectorType;
using DiagonalBase::m_coeffs;
public:
/** Default constructor without initialization */
inline DiagonalMatrix() : DiagonalBase()
{}
/** Constructs a diagonal matrix with given dimension */
inline DiagonalMatrix(int dim) : DiagonalBase(dim)
{}
/** 2D only */
inline DiagonalMatrix(const Scalar& sx, const Scalar& sy)
{
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,2,2);
m_coeffs.x() = sx;
m_coeffs.y() = sy;
}
/** 3D only */
inline DiagonalMatrix(const Scalar& sx, const Scalar& sy, const Scalar& sz)
{
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,3,3);
m_coeffs.x() = sx;
m_coeffs.y() = sy;
m_coeffs.z() = sz;
}
/** copy constructor */
inline DiagonalMatrix(const DiagonalMatrix& other) : DiagonalBase(other.m_coeffs)
{}
/** generic constructor from expression */
template<typename OtherDerived>
explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : DiagonalBase(other)
{}
DiagonalMatrix& operator=(const DiagonalMatrix& other)
{
m_coeffs = other.m_coeffs;
return *this;
}
template<typename OtherDerived>
DiagonalMatrix& operator=(const MatrixBase<OtherDerived>& other)
{
EIGEN_STATIC_ASSERT((OtherDerived::Flags&Diagonal)==Diagonal, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX);
m_coeffs = other.diagonal();
return *this;
}
};
/** \class DiagonalMatrixWrapper
* \nonstableyet
*
* \brief Expression of a diagonal matrix
*
* \param CoeffsVectorType the type of the vector of diagonal coefficients
*
* This class is an expression of a diagonal matrix with given vector of diagonal
* coefficients. It is the return
* type of MatrixBase::diagonal(const OtherDerived&) and most of the time this is
* the only way it is used.
* coefficients. It is the return type of MatrixBase::diagonal(const OtherDerived&)
* and most of the time this is the only way it is used.
*
* \sa MatrixBase::diagonal(const OtherDerived&)
* \sa class DiagonalMatrixBase, class DiagonalMatrix, MatrixBase::asDiagonal()
*/
template<typename CoeffsVectorType>
struct ei_traits<DiagonalMatrix<CoeffsVectorType> >
struct ei_traits<DiagonalMatrixWrapper<CoeffsVectorType> >
{
typedef typename CoeffsVectorType::Scalar Scalar;
typedef typename ei_nested<CoeffsVectorType>::type CoeffsVectorTypeNested;
@@ -54,45 +240,19 @@ struct ei_traits<DiagonalMatrix<CoeffsVectorType> >
CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost
};
};
template<typename CoeffsVectorType>
class DiagonalMatrix : ei_no_assignment_operator,
public MatrixBase<DiagonalMatrix<CoeffsVectorType> >
class DiagonalMatrixWrapper
: public DiagonalMatrixBase<typename CoeffsVectorType::Nested, DiagonalMatrixWrapper<CoeffsVectorType> >
{
typedef typename CoeffsVectorType::Nested CoeffsVectorTypeNested;
typedef DiagonalMatrixBase<CoeffsVectorTypeNested, DiagonalMatrixWrapper<CoeffsVectorType> > DiagonalBase;
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix)
// needed to evaluate a DiagonalMatrix<Xpr> to a DiagonalMatrix<NestByValue<Vector> >
template<typename OtherCoeffsVectorType>
inline DiagonalMatrix(const DiagonalMatrix<OtherCoeffsVectorType>& other) : m_coeffs(other.diagonal())
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherCoeffsVectorType);
ei_assert(m_coeffs.size() > 0);
}
inline DiagonalMatrix(const CoeffsVectorType& coeffs) : m_coeffs(coeffs)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
ei_assert(coeffs.size() > 0);
}
inline int rows() const { return m_coeffs.size(); }
inline int cols() const { return m_coeffs.size(); }
inline const Scalar coeff(int row, int col) const
{
return row == col ? m_coeffs.coeff(row) : static_cast<Scalar>(0);
}
inline const CoeffsVectorType& diagonal() const { return m_coeffs; }
protected:
const typename CoeffsVectorType::Nested m_coeffs;
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrixWrapper)
inline DiagonalMatrixWrapper(const CoeffsVectorType& coeffs) : DiagonalBase(coeffs)
{}
};
/** \nonstableyet
/** \nonstableyet
* \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
*
* \only_for_vectors
@@ -105,13 +265,13 @@ class DiagonalMatrix : ei_no_assignment_operator,
* \sa class DiagonalMatrix, isDiagonal()
**/
template<typename Derived>
inline const DiagonalMatrix<Derived>
inline const DiagonalMatrixWrapper<Derived>
MatrixBase<Derived>::asDiagonal() const
{
return derived();
}
/** \nonstableyet
/** \nonstableyet
* \returns true if *this is approximately equal to a diagonal matrix,
* within the precision given by \a prec.
*