From bfdc1c49730c79e6058ba1506628341559670c25 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Sat, 8 May 2010 13:45:31 -0400 Subject: [PATCH] introduce DenseCoeffsBase: this is where the coeff / coeffRef / etc... methods go. Rationale: coeffRef() methods should only exist when we have DirectAccess. So a natural thing to do would have been to use enable_if, but since there are many methods it made more sense to do the "enable_if" for the whole group by introducing a new class. And that also that the benefit of not changing method prototypes. --- Eigen/Core | 2 +- Eigen/src/Core/Coeffs.h | 827 +++++++++++----------- Eigen/src/Core/DenseBase.h | 96 +-- Eigen/src/Core/EigenBase.h | 3 + Eigen/src/Core/util/ForwardDeclarations.h | 16 +- Eigen/src/Core/util/XprHelper.h | 4 +- test/basicstuff.cpp | 2 + 7 files changed, 471 insertions(+), 479 deletions(-) diff --git a/Eigen/Core b/Eigen/Core index 0b2608036..464eb93f1 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -232,10 +232,10 @@ using std::size_t; #include "src/Core/arch/Default/Settings.h" #include "src/Core/Functors.h" +#include "src/Core/Coeffs.h" #include "src/Core/DenseBase.h" #include "src/Core/MatrixBase.h" #include "src/Core/EigenBase.h" -#include "src/Core/Coeffs.h" #ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874 // at least confirmed with Doxygen 1.5.5 and 1.5.6 diff --git a/Eigen/src/Core/Coeffs.h b/Eigen/src/Core/Coeffs.h index b26f3a4e4..661e57e74 100644 --- a/Eigen/src/Core/Coeffs.h +++ b/Eigen/src/Core/Coeffs.h @@ -25,448 +25,479 @@ #ifndef EIGEN_COEFFS_H #define EIGEN_COEFFS_H -template -EIGEN_STRONG_INLINE int DenseBase::rowIndexByOuterInner(int outer, int inner) +template +class DenseCoeffsBase : public EigenBase { - return int(Derived::RowsAtCompileTime) == 1 ? 0 - : int(Derived::ColsAtCompileTime) == 1 ? inner - : int(Derived::Flags)&RowMajorBit ? outer - : inner; -} + public: + typedef typename ei_traits::Scalar Scalar; + typedef typename ei_meta_if::ret, const Scalar&, Scalar>::ret CoeffReturnType; + + typedef EigenBase Base; + using Base::rows; + using Base::cols; + using Base::size; + using Base::derived; + + EIGEN_STRONG_INLINE int rowIndexByOuterInner(int outer, int inner) const + { + return int(Derived::RowsAtCompileTime) == 1 ? 0 + : int(Derived::ColsAtCompileTime) == 1 ? inner + : int(Derived::Flags)&RowMajorBit ? outer + : inner; + } + + EIGEN_STRONG_INLINE int colIndexByOuterInner(int outer, int inner) const + { + return int(Derived::ColsAtCompileTime) == 1 ? 0 + : int(Derived::RowsAtCompileTime) == 1 ? inner + : int(Derived::Flags)&RowMajorBit ? inner + : outer; + } + + /** Short version: don't use this function, use + * \link operator()(int,int) const \endlink instead. + * + * Long version: this function is similar to + * \link operator()(int,int) const \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator()(int,int) const \endlink. + * + * \sa operator()(int,int) const, coeffRef(int,int), coeff(int) const + */ + EIGEN_STRONG_INLINE const CoeffReturnType coeff(int row, int col) const + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().coeff(row, col); + } + + EIGEN_STRONG_INLINE const CoeffReturnType coeffByOuterInner(int outer, int inner) const + { + return coeff(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner)); + } + + /** \returns the coefficient at given the given row and column. + * + * \sa operator()(int,int), operator[](int) + */ + EIGEN_STRONG_INLINE const CoeffReturnType operator()(int row, int col) const + { + ei_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().coeff(row, col); + } + + /** Short version: don't use this function, use + * \link operator[](int) const \endlink instead. + * + * Long version: this function is similar to + * \link operator[](int) const \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameter \a index is in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator[](int) const \endlink. + * + * \sa operator[](int) const, coeffRef(int), coeff(int,int) const + */ + + EIGEN_STRONG_INLINE const CoeffReturnType + coeff(int index) const + { + ei_internal_assert(index >= 0 && index < size()); + return derived().coeff(index); + } + + + /** \returns the coefficient at given index. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](int), operator()(int,int) const, x() const, y() const, + * z() const, w() const + */ + + EIGEN_STRONG_INLINE const CoeffReturnType + operator[](int index) const + { + EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) + ei_assert(index >= 0 && index < size()); + return derived().coeff(index); + } + + /** \returns the coefficient at given index. + * + * This is synonymous to operator[](int) const. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](int), operator()(int,int) const, x() const, y() const, + * z() const, w() const + */ + + EIGEN_STRONG_INLINE const CoeffReturnType + operator()(int index) const + { + ei_assert(index >= 0 && index < size()); + return derived().coeff(index); + } + + /** equivalent to operator[](0). */ + + EIGEN_STRONG_INLINE const CoeffReturnType + x() const { return (*this)[0]; } + + /** equivalent to operator[](1). */ + + EIGEN_STRONG_INLINE const CoeffReturnType + y() const { return (*this)[1]; } + + /** equivalent to operator[](2). */ + + EIGEN_STRONG_INLINE const CoeffReturnType + z() const { return (*this)[2]; } + + /** equivalent to operator[](3). */ + + EIGEN_STRONG_INLINE const CoeffReturnType + w() const { return (*this)[3]; } + + /** \returns the packet of coefficients starting at the given row and column. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit. + * + * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ + + template + EIGEN_STRONG_INLINE typename ei_packet_traits::type + packet(int row, int col) const + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().template packet(row,col); + } + + + template + EIGEN_STRONG_INLINE typename ei_packet_traits::type + packetByOuterInner(int outer, int inner) const + { + return packet(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner)); + } + + /** \returns the packet of coefficients starting at the given index. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit and the LinearAccessBit. + * + * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ + + template + EIGEN_STRONG_INLINE typename ei_packet_traits::type + packet(int index) const + { + ei_internal_assert(index >= 0 && index < size()); + return derived().template packet(index); + } + + void coeffRef(); + void coeffRefByOuterInner(); + void writePacket(); + void writePacketByOuterInner(); + void copyCoeff(); + void copyCoeffByOuterInner(); + void copyPacket(); + void copyPacketByOuterInner(); +}; template -EIGEN_STRONG_INLINE int DenseBase::colIndexByOuterInner(int outer, int inner) +class DenseCoeffsBase : public DenseCoeffsBase { - return int(Derived::ColsAtCompileTime) == 1 ? 0 - : int(Derived::RowsAtCompileTime) == 1 ? inner - : int(Derived::Flags)&RowMajorBit ? inner - : outer; -} + public: -/** Short version: don't use this function, use - * \link operator()(int,int) const \endlink instead. - * - * Long version: this function is similar to - * \link operator()(int,int) const \endlink, but without the assertion. - * Use this for limiting the performance cost of debugging code when doing - * repeated coefficient access. Only use this when it is guaranteed that the - * parameters \a row and \a col are in range. - * - * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this - * function equivalent to \link operator()(int,int) const \endlink. - * - * \sa operator()(int,int) const, coeffRef(int,int), coeff(int) const - */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::coeff(int row, int col) const -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeff(row, col); -} + typedef DenseCoeffsBase Base; + typedef typename ei_traits::Scalar Scalar; + using Base::CoeffReturnType; + using Base::coeff; + using Base::rows; + using Base::cols; + using Base::size; + using Base::derived; + using Base::rowIndexByOuterInner; + using Base::colIndexByOuterInner; -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::coeffByOuterInner(int outer, int inner) const -{ - return coeff(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner)); -} + /** Short version: don't use this function, use + * \link operator()(int,int) \endlink instead. + * + * Long version: this function is similar to + * \link operator()(int,int) \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator()(int,int) \endlink. + * + * \sa operator()(int,int), coeff(int, int) const, coeffRef(int) + */ + EIGEN_STRONG_INLINE Scalar& coeffRef(int row, int col) + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().coeffRef(row, col); + } -/** \returns the coefficient at given the given row and column. - * - * \sa operator()(int,int), operator[](int) const - */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::operator()(int row, int col) const -{ - ei_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeff(row, col); -} + EIGEN_STRONG_INLINE Scalar& + coeffRefByOuterInner(int outer, int inner) + { + return coeffRef(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner)); + } -/** Short version: don't use this function, use - * \link operator()(int,int) \endlink instead. - * - * Long version: this function is similar to - * \link operator()(int,int) \endlink, but without the assertion. - * Use this for limiting the performance cost of debugging code when doing - * repeated coefficient access. Only use this when it is guaranteed that the - * parameters \a row and \a col are in range. - * - * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this - * function equivalent to \link operator()(int,int) \endlink. - * - * \sa operator()(int,int), coeff(int, int) const, coeffRef(int) - */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::coeffRef(int row, int col) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeffRef(row, col); -} + /** \returns a reference to the coefficient at given the given row and column. + * + * \sa operator[](int) + */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::coeffRefByOuterInner(int outer, int inner) -{ - return coeffRef(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner)); -} + EIGEN_STRONG_INLINE Scalar& + operator()(int row, int col) + { + ei_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().coeffRef(row, col); + } -/** \returns a reference to the coefficient at given the given row and column. - * - * \sa operator()(int,int) const, operator[](int) - */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::operator()(int row, int col) -{ - ei_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeffRef(row, col); -} -/** Short version: don't use this function, use - * \link operator[](int) const \endlink instead. - * - * Long version: this function is similar to - * \link operator[](int) const \endlink, but without the assertion. - * Use this for limiting the performance cost of debugging code when doing - * repeated coefficient access. Only use this when it is guaranteed that the - * parameter \a index is in range. - * - * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this - * function equivalent to \link operator[](int) const \endlink. - * - * \sa operator[](int) const, coeffRef(int), coeff(int,int) const - */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::coeff(int index) const -{ - ei_internal_assert(index >= 0 && index < size()); - return derived().coeff(index); -} + /** Short version: don't use this function, use + * \link operator[](int) \endlink instead. + * + * Long version: this function is similar to + * \link operator[](int) \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator[](int) \endlink. + * + * \sa operator[](int), coeff(int) const, coeffRef(int,int) + */ -/** \returns the coefficient at given index. - * - * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. - * - * \sa operator[](int), operator()(int,int) const, x() const, y() const, - * z() const, w() const - */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::operator[](int index) const -{ - EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, - THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) - ei_assert(index >= 0 && index < size()); - return derived().coeff(index); -} + EIGEN_STRONG_INLINE Scalar& + coeffRef(int index) + { + ei_internal_assert(index >= 0 && index < size()); + return derived().coeffRef(index); + } -/** \returns the coefficient at given index. - * - * This is synonymous to operator[](int) const. - * - * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. - * - * \sa operator[](int), operator()(int,int) const, x() const, y() const, - * z() const, w() const - */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::operator()(int index) const -{ - ei_assert(index >= 0 && index < size()); - return derived().coeff(index); -} + /** \returns a reference to the coefficient at given index. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w() + */ -/** Short version: don't use this function, use - * \link operator[](int) \endlink instead. - * - * Long version: this function is similar to - * \link operator[](int) \endlink, but without the assertion. - * Use this for limiting the performance cost of debugging code when doing - * repeated coefficient access. Only use this when it is guaranteed that the - * parameters \a row and \a col are in range. - * - * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this - * function equivalent to \link operator[](int) \endlink. - * - * \sa operator[](int), coeff(int) const, coeffRef(int,int) - */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::coeffRef(int index) -{ - ei_internal_assert(index >= 0 && index < size()); - return derived().coeffRef(index); -} + EIGEN_STRONG_INLINE Scalar& + operator[](int index) + { + EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) + ei_assert(index >= 0 && index < size()); + return derived().coeffRef(index); + } -/** \returns a reference to the coefficient at given index. - * - * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. - * - * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w() - */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::operator[](int index) -{ - EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, - THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) - ei_assert(index >= 0 && index < size()); - return derived().coeffRef(index); -} + /** \returns a reference to the coefficient at given index. + * + * This is synonymous to operator[](int). + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w() + */ -/** \returns a reference to the coefficient at given index. - * - * This is synonymous to operator[](int). - * - * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. - * - * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w() - */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::operator()(int index) -{ - ei_assert(index >= 0 && index < size()); - return derived().coeffRef(index); -} + EIGEN_STRONG_INLINE Scalar& + operator()(int index) + { + ei_assert(index >= 0 && index < size()); + return derived().coeffRef(index); + } -/** equivalent to operator[](0). */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::x() const { return (*this)[0]; } + /** equivalent to operator[](0). */ -/** equivalent to operator[](1). */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::y() const { return (*this)[1]; } + EIGEN_STRONG_INLINE Scalar& + x() { return (*this)[0]; } -/** equivalent to operator[](2). */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::z() const { return (*this)[2]; } + /** equivalent to operator[](1). */ -/** equivalent to operator[](3). */ -template -EIGEN_STRONG_INLINE const typename DenseBase::CoeffReturnType DenseBase - ::w() const { return (*this)[3]; } + EIGEN_STRONG_INLINE Scalar& + y() { return (*this)[1]; } -/** equivalent to operator[](0). */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::x() { return (*this)[0]; } + /** equivalent to operator[](2). */ -/** equivalent to operator[](1). */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::y() { return (*this)[1]; } + EIGEN_STRONG_INLINE Scalar& + z() { return (*this)[2]; } -/** equivalent to operator[](2). */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::z() { return (*this)[2]; } + /** equivalent to operator[](3). */ -/** equivalent to operator[](3). */ -template -EIGEN_STRONG_INLINE typename ei_traits::Scalar& DenseBase - ::w() { return (*this)[3]; } + EIGEN_STRONG_INLINE Scalar& + w() { return (*this)[3]; } -/** \returns the packet of coefficients starting at the given row and column. It is your responsibility - * to ensure that a packet really starts there. This method is only available on expressions having the - * PacketAccessBit. - * - * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select - * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets - * starting at an address which is a multiple of the packet size. - */ -template -template -EIGEN_STRONG_INLINE typename ei_packet_traits::Scalar>::type -DenseBase::packet(int row, int col) const -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().template packet(row,col); -} + /** Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit. + * + * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ -template -template -EIGEN_STRONG_INLINE typename ei_packet_traits::Scalar>::type -DenseBase::packetByOuterInner(int outer, int inner) const -{ - return packet(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner)); -} + template + EIGEN_STRONG_INLINE void writePacket + (int row, int col, const typename ei_packet_traits::type& x) + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + derived().template writePacket(row,col,x); + } -/** Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility - * to ensure that a packet really starts there. This method is only available on expressions having the - * PacketAccessBit. - * - * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select - * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets - * starting at an address which is a multiple of the packet size. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::writePacket -(int row, int col, const typename ei_packet_traits::Scalar>::type& x) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - derived().template writePacket(row,col,x); -} -template -template -EIGEN_STRONG_INLINE void DenseBase::writePacketByOuterInner -(int outer, int inner, const typename ei_packet_traits::Scalar>::type& x) -{ - writePacket(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner), - x); -} + template + EIGEN_STRONG_INLINE void writePacketByOuterInner + (int outer, int inner, const typename ei_packet_traits::type& x) + { + writePacket(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner), + x); + } -/** \returns the packet of coefficients starting at the given index. It is your responsibility - * to ensure that a packet really starts there. This method is only available on expressions having the - * PacketAccessBit and the LinearAccessBit. - * - * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select - * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets - * starting at an address which is a multiple of the packet size. - */ -template -template -EIGEN_STRONG_INLINE typename ei_packet_traits::Scalar>::type -DenseBase::packet(int index) const -{ - ei_internal_assert(index >= 0 && index < size()); - return derived().template packet(index); -} + /** Stores the given packet of coefficients, at the given index in this expression. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit and the LinearAccessBit. + * + * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ -/** Stores the given packet of coefficients, at the given index in this expression. It is your responsibility - * to ensure that a packet really starts there. This method is only available on expressions having the - * PacketAccessBit and the LinearAccessBit. - * - * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select - * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets - * starting at an address which is a multiple of the packet size. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::writePacket -(int index, const typename ei_packet_traits::Scalar>::type& x) -{ - ei_internal_assert(index >= 0 && index < size()); - derived().template writePacket(index,x); -} + template + EIGEN_STRONG_INLINE void writePacket + (int index, const typename ei_packet_traits::type& x) + { + ei_internal_assert(index >= 0 && index < size()); + derived().template writePacket(index,x); + } #ifndef EIGEN_PARSED_BY_DOXYGEN -/** \internal Copies the coefficient at position (row,col) of other into *this. - * - * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code - * with usual assignments. - * - * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::copyCoeff(int row, int col, const DenseBase& other) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - derived().coeffRef(row, col) = other.derived().coeff(row, col); -} + /** \internal Copies the coefficient at position (row,col) of other into *this. + * + * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code + * with usual assignments. + * + * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. + */ -/** \internal Copies the coefficient at the given index of other into *this. - * - * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code - * with usual assignments. - * - * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::copyCoeff(int index, const DenseBase& other) -{ - ei_internal_assert(index >= 0 && index < size()); - derived().coeffRef(index) = other.derived().coeff(index); -} + template + EIGEN_STRONG_INLINE void copyCoeff(int row, int col, const DenseBase& other) + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + derived().coeffRef(row, col) = other.derived().coeff(row, col); + } -template -template -EIGEN_STRONG_INLINE void DenseBase::copyCoeffByOuterInner(int outer, int inner, const DenseBase& other) -{ - const int row = Derived::rowIndexByOuterInner(outer,inner); - const int col = Derived::colIndexByOuterInner(outer,inner); - // derived() is important here: copyCoeff() may be reimplemented in Derived! - derived().copyCoeff(row, col, other); -} + /** \internal Copies the coefficient at the given index of other into *this. + * + * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code + * with usual assignments. + * + * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. + */ -/** \internal Copies the packet at position (row,col) of other into *this. - * - * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code - * with usual assignments. - * - * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::copyPacket(int row, int col, const DenseBase& other) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - derived().template writePacket(row, col, - other.derived().template packet(row, col)); -} + template + EIGEN_STRONG_INLINE void copyCoeff(int index, const DenseBase& other) + { + ei_internal_assert(index >= 0 && index < size()); + derived().coeffRef(index) = other.derived().coeff(index); + } -/** \internal Copies the packet at the given index of other into *this. - * - * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code - * with usual assignments. - * - * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. - */ -template -template -EIGEN_STRONG_INLINE void DenseBase::copyPacket(int index, const DenseBase& other) -{ - ei_internal_assert(index >= 0 && index < size()); - derived().template writePacket(index, - other.derived().template packet(index)); -} -template -template -EIGEN_STRONG_INLINE void DenseBase::copyPacketByOuterInner(int outer, int inner, const DenseBase& other) -{ - const int row = Derived::rowIndexByOuterInner(outer,inner); - const int col = Derived::colIndexByOuterInner(outer,inner); - // derived() is important here: copyCoeff() may be reimplemented in Derived! - derived().copyPacket(row, col, other); -} + template + EIGEN_STRONG_INLINE void copyCoeffByOuterInner(int outer, int inner, const DenseBase& other) + { + const int row = rowIndexByOuterInner(outer,inner); + const int col = colIndexByOuterInner(outer,inner); + // derived() is important here: copyCoeff() may be reimplemented in Derived! + derived().copyCoeff(row, col, other); + } + + /** \internal Copies the packet at position (row,col) of other into *this. + * + * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code + * with usual assignments. + * + * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. + */ + + template + EIGEN_STRONG_INLINE void copyPacket(int row, int col, const DenseBase& other) + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + derived().template writePacket(row, col, + other.derived().template packet(row, col)); + } + + /** \internal Copies the packet at the given index of other into *this. + * + * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code + * with usual assignments. + * + * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. + */ + + template + EIGEN_STRONG_INLINE void copyPacket(int index, const DenseBase& other) + { + ei_internal_assert(index >= 0 && index < size()); + derived().template writePacket(index, + other.derived().template packet(index)); + } + + template + EIGEN_STRONG_INLINE void copyPacketByOuterInner(int outer, int inner, const DenseBase& other) + { + const int row = rowIndexByOuterInner(outer,inner); + const int col = colIndexByOuterInner(outer,inner); + // derived() is important here: copyCoeff() may be reimplemented in Derived! + derived().copyPacket(row, col, other); + } +#endif +}; template struct ei_first_aligned_impl { - inline static int run(const DenseBase&) + inline static int run(const Derived&) { return 0; } }; template struct ei_first_aligned_impl { - inline static int run(const DenseBase& m) + inline static int run(const Derived& m) { return ei_first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size()); } @@ -478,13 +509,11 @@ struct ei_first_aligned_impl * documentation. */ template -inline static int ei_first_aligned(const DenseBase& m) +inline static int ei_first_aligned(const Derived& m) { return ei_first_aligned_impl - - ::run(m); + + ::run(m); } -#endif - #endif // EIGEN_COEFFS_H diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 8bdcbf52b..f686885b3 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -64,7 +64,7 @@ template class DenseBase : public ei_special_scalar_op_base::Scalar, typename NumTraits::Scalar>::Real> #else - : public EigenBase + : public DenseCoeffsBase #endif // not EIGEN_PARSED_BY_DOXYGEN { public: @@ -76,9 +76,33 @@ template class DenseBase typedef typename ei_traits::Scalar Scalar; typedef typename ei_packet_traits::type PacketScalar; + typedef DenseCoeffsBase Base; + using Base::derived; + using Base::const_cast_derived; + using Base::rows; + using Base::cols; + using Base::size; + using Base::rowIndexByOuterInner; + using Base::colIndexByOuterInner; + using Base::coeff; + using Base::coeffByOuterInner; + using Base::packet; + using Base::packetByOuterInner; + using Base::writePacket; + using Base::writePacketByOuterInner; + using Base::coeffRef; + using Base::coeffRefByOuterInner; + using Base::copyCoeff; + using Base::copyCoeffByOuterInner; + using Base::copyPacket; + using Base::copyPacketByOuterInner; + using Base::operator(); + using Base::operator[]; + using Base::x; + using Base::y; + using Base::z; + using Base::w; - using EigenBase::derived; - using EigenBase::const_cast_derived; #endif // not EIGEN_PARSED_BY_DOXYGEN enum { @@ -172,13 +196,6 @@ template class DenseBase typedef typename NumTraits::Real RealScalar; #endif // not EIGEN_PARSED_BY_DOXYGEN - /** \returns the number of rows. \sa cols(), RowsAtCompileTime */ - inline int rows() const { return derived().rows(); } - /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ - inline int cols() const { return derived().cols(); } - /** \returns the number of coefficients, which is rows()*cols(). - * \sa rows(), cols(), SizeAtCompileTime. */ - inline int size() const { return rows() * cols(); } /** \returns the number of nonzero coefficients which is in practice the number * of stored coefficients. */ inline int nonZeros() const { return size(); } @@ -257,15 +274,6 @@ template class DenseBase #endif // not EIGEN_PARSED_BY_DOXYGEN - const CoeffReturnType x() const; - const CoeffReturnType y() const; - const CoeffReturnType z() const; - const CoeffReturnType w() const; - Scalar& x(); - Scalar& y(); - Scalar& z(); - Scalar& w(); - /** Copies \a other into *this. \returns a reference to *this. */ template Derived& operator=(const DenseBase& other); @@ -343,56 +351,6 @@ template class DenseBase template CommaInitializer operator<< (const DenseBase& other); - const CoeffReturnType coeff(int row, int col) const; - const CoeffReturnType coeffByOuterInner(int outer, int inner) const; - const CoeffReturnType operator()(int row, int col) const; - - Scalar& coeffRef(int row, int col); - Scalar& coeffRefByOuterInner(int outer, int inner); - Scalar& operator()(int row, int col); - - const CoeffReturnType coeff(int index) const; - const CoeffReturnType operator[](int index) const; - const CoeffReturnType operator()(int index) const; - - Scalar& coeffRef(int index); - Scalar& operator[](int index); - Scalar& operator()(int index); - -#ifndef EIGEN_PARSED_BY_DOXYGEN - template - void copyCoeff(int row, int col, const DenseBase& other); - template - void copyCoeffByOuterInner(int outer, int inner, const DenseBase& other); - template - void copyCoeff(int index, const DenseBase& other); - template - void copyPacket(int row, int col, const DenseBase& other); - template - void copyPacketByOuterInner(int outer, int inner, const DenseBase& other); - template - void copyPacket(int index, const DenseBase& other); - - private: - static int rowIndexByOuterInner(int outer, int inner); - static int colIndexByOuterInner(int outer, int inner); - public: -#endif // not EIGEN_PARSED_BY_DOXYGEN - - template - PacketScalar packet(int row, int col) const; - template - PacketScalar packetByOuterInner(int outer, int inner) const; - template - void writePacket(int row, int col, const PacketScalar& x); - template - void writePacketByOuterInner(int outer, int inner, const PacketScalar& x); - - template - PacketScalar packet(int index) const; - template - void writePacket(int index, const PacketScalar& x); - Eigen::Transpose transpose(); const Eigen::Transpose transpose() const; void transposeInPlace(); diff --git a/Eigen/src/Core/EigenBase.h b/Eigen/src/Core/EigenBase.h index cf1ce4376..e583fddc3 100644 --- a/Eigen/src/Core/EigenBase.h +++ b/Eigen/src/Core/EigenBase.h @@ -51,6 +51,9 @@ template struct EigenBase inline int rows() const { return derived().rows(); } /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ inline int cols() const { return derived().cols(); } + /** \returns the number of coefficients, which is rows()*cols(). + * \sa rows(), cols(), SizeAtCompileTime. */ + inline int size() const { return rows() * cols(); } /** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */ template inline void evalTo(Dest& dst) const diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index d660078c7..9debb9409 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -29,7 +29,15 @@ template struct ei_traits; template struct NumTraits; +template struct ei_has_direct_access +{ + enum { ret = (ei_traits::Flags & DirectAccessBit) ? 1 : 0 }; +}; + template struct EigenBase; +template struct DenseBase; +template::ret> +class DenseCoeffsBase; template class NestByValue; template class ForceAlignedAccess; template class SwapWrapper; -// MSVC has a big bug: when the expression ei_traits::Flags&DirectAccessBit ? 1 : 0 -// is used as default template parameter value here, it gets mis-evaluated as just ei_traits::Flags -// Moreover, adding brackets tends to give compilation errors with MSVC. -// Solution: defer that to a helper struct. -template struct ei_has_direct_access -{ - enum { ret = (ei_traits::Flags & DirectAccessBit) ? 1 : 0 }; -}; template::ret> class Block; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index ada93bcd4..667418bb3 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -325,7 +325,7 @@ struct ei_dense_xpr_base * overloads for complex types */ template::ret > -struct ei_special_scalar_op_base : public EigenBase +struct ei_special_scalar_op_base : public DenseCoeffsBase { // dummy operator* so that the // "using ei_special_scalar_op_base::operator*" compiles @@ -333,7 +333,7 @@ struct ei_special_scalar_op_base : public EigenBase }; template -struct ei_special_scalar_op_base : public EigenBase +struct ei_special_scalar_op_base : public DenseCoeffsBase { const CwiseUnaryOp, Derived> operator*(const OtherScalar& scalar) const diff --git a/test/basicstuff.cpp b/test/basicstuff.cpp index 7244dff9d..7ef127ac2 100644 --- a/test/basicstuff.cpp +++ b/test/basicstuff.cpp @@ -152,6 +152,7 @@ template void basicStuffComplex(const MatrixType& m) VERIFY(!static_cast(cm).imag().isZero()); } +#ifdef EIGEN_TEST_PART_2 void casting() { Matrix4f m = Matrix4f::Random(), m2; @@ -160,6 +161,7 @@ void casting() m2 = m.cast(); // check the specialization when NewType == Type VERIFY(m.isApprox(m2)); } +#endif void test_basicstuff() {