diff options
author | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-05-08 13:45:31 -0400 |
---|---|---|
committer | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-05-08 13:45:31 -0400 |
commit | bfdc1c49730c79e6058ba1506628341559670c25 (patch) | |
tree | cff450947e3fe4dabc07a382061c4664970a3a90 | |
parent | d03779f75f3a29b6cc76299f511aefc902771e4c (diff) |
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.
-rw-r--r-- | Eigen/Core | 2 | ||||
-rw-r--r-- | Eigen/src/Core/Coeffs.h | 889 | ||||
-rw-r--r-- | Eigen/src/Core/DenseBase.h | 96 | ||||
-rw-r--r-- | Eigen/src/Core/EigenBase.h | 3 | ||||
-rw-r--r-- | Eigen/src/Core/util/ForwardDeclarations.h | 16 | ||||
-rw-r--r-- | Eigen/src/Core/util/XprHelper.h | 4 | ||||
-rw-r--r-- | test/basicstuff.cpp | 2 |
7 files changed, 502 insertions, 510 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<typename Derived> -EIGEN_STRONG_INLINE int DenseBase<Derived>::rowIndexByOuterInner(int outer, int inner) -{ - return int(Derived::RowsAtCompileTime) == 1 ? 0 - : int(Derived::ColsAtCompileTime) == 1 ? inner - : int(Derived::Flags)&RowMajorBit ? outer - : inner; -} - -template<typename Derived> -EIGEN_STRONG_INLINE int DenseBase<Derived>::colIndexByOuterInner(int outer, int inner) -{ - 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 - */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::coeff(int row, int col) const -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeff(row, col); -} - -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::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) const - */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::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,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<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::coeffRef(int row, int col) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().coeffRef(row, col); -} - -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::coeffRefByOuterInner(int outer, int inner) -{ - return coeffRef(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner)); -} - -/** \returns a reference to the coefficient at given the given row and column. - * - * \sa operator()(int,int) const, operator[](int) - */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::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<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::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 - */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::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 - */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::operator()(int index) const -{ - ei_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) - */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::coeffRef(int index) -{ - ei_internal_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<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::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() - */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::operator()(int index) +template<typename Derived, bool EnableDirectAccessAPI> +class DenseCoeffsBase : public EigenBase<Derived> { - ei_assert(index >= 0 && index < size()); - return derived().coeffRef(index); -} - -/** equivalent to operator[](0). */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::x() const { return (*this)[0]; } - -/** equivalent to operator[](1). */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::y() const { return (*this)[1]; } - -/** equivalent to operator[](2). */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::z() const { return (*this)[2]; } - -/** equivalent to operator[](3). */ -template<typename Derived> -EIGEN_STRONG_INLINE const typename DenseBase<Derived>::CoeffReturnType DenseBase<Derived> - ::w() const { return (*this)[3]; } - -/** equivalent to operator[](0). */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::x() { return (*this)[0]; } - -/** equivalent to operator[](1). */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::y() { return (*this)[1]; } - -/** equivalent to operator[](2). */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::z() { return (*this)[2]; } - -/** equivalent to operator[](3). */ -template<typename Derived> -EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& DenseBase<Derived> - ::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<typename Derived> -template<int LoadMode> -EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type -DenseBase<Derived>::packet(int row, int col) const -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - return derived().template packet<LoadMode>(row,col); -} - -template<typename Derived> -template<int LoadMode> -EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type -DenseBase<Derived>::packetByOuterInner(int outer, int inner) const -{ - return packet<LoadMode>(rowIndexByOuterInner(outer, inner), - colIndexByOuterInner(outer, inner)); -} - -/** 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<typename Derived> -template<int StoreMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::writePacket -(int row, int col, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - derived().template writePacket<StoreMode>(row,col,x); -} - -template<typename Derived> -template<int StoreMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::writePacketByOuterInner -(int outer, int inner, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x) -{ - writePacket<StoreMode>(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<typename Derived> -template<int LoadMode> -EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type -DenseBase<Derived>::packet(int index) const -{ - ei_internal_assert(index >= 0 && index < size()); - return derived().template packet<LoadMode>(index); -} + public: + typedef typename ei_traits<Derived>::Scalar Scalar; + typedef typename ei_meta_if<ei_has_direct_access<Derived>::ret, const Scalar&, Scalar>::ret CoeffReturnType; + + typedef EigenBase<Derived> 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<int LoadMode> + EIGEN_STRONG_INLINE typename ei_packet_traits<Scalar>::type + packet(int row, int col) const + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + return derived().template packet<LoadMode>(row,col); + } + + + template<int LoadMode> + EIGEN_STRONG_INLINE typename ei_packet_traits<Scalar>::type + packetByOuterInner(int outer, int inner) const + { + return packet<LoadMode>(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<int LoadMode> + EIGEN_STRONG_INLINE typename ei_packet_traits<Scalar>::type + packet(int index) const + { + ei_internal_assert(index >= 0 && index < size()); + return derived().template packet<LoadMode>(index); + } + + void coeffRef(); + void coeffRefByOuterInner(); + void writePacket(); + void writePacketByOuterInner(); + void copyCoeff(); + void copyCoeffByOuterInner(); + void copyPacket(); + void copyPacketByOuterInner(); +}; -/** 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<typename Derived> -template<int StoreMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::writePacket -(int index, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x) +class DenseCoeffsBase<Derived, true> : public DenseCoeffsBase<Derived, false> { - ei_internal_assert(index >= 0 && index < size()); - derived().template writePacket<StoreMode>(index,x); -} + public: + + typedef DenseCoeffsBase<Derived, false> Base; + typedef typename ei_traits<Derived>::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; + + /** 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); + } + + EIGEN_STRONG_INLINE Scalar& + coeffRefByOuterInner(int outer, int inner) + { + return coeffRef(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner)); + } + + /** \returns a reference to the coefficient at given the given row and column. + * + * \sa operator[](int) + */ + + EIGEN_STRONG_INLINE Scalar& + 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) \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) + */ + + EIGEN_STRONG_INLINE Scalar& + coeffRef(int index) + { + ei_internal_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() + */ + + 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 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() + */ + + EIGEN_STRONG_INLINE Scalar& + operator()(int index) + { + ei_assert(index >= 0 && index < size()); + return derived().coeffRef(index); + } + + /** equivalent to operator[](0). */ + + EIGEN_STRONG_INLINE Scalar& + x() { return (*this)[0]; } + + /** equivalent to operator[](1). */ + + EIGEN_STRONG_INLINE Scalar& + y() { return (*this)[1]; } + + /** equivalent to operator[](2). */ + + EIGEN_STRONG_INLINE Scalar& + z() { return (*this)[2]; } + + /** equivalent to operator[](3). */ + + EIGEN_STRONG_INLINE Scalar& + w() { return (*this)[3]; } + + /** 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<int StoreMode> + EIGEN_STRONG_INLINE void 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<StoreMode>(row,col,x); + } + + + template<int StoreMode> + EIGEN_STRONG_INLINE void writePacketByOuterInner + (int outer, int inner, const typename ei_packet_traits<Scalar>::type& x) + { + writePacket<StoreMode>(rowIndexByOuterInner(outer, inner), + colIndexByOuterInner(outer, inner), + x); + } + + /** 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<int StoreMode> + EIGEN_STRONG_INLINE void writePacket + (int index, const typename ei_packet_traits<Scalar>::type& x) + { + ei_internal_assert(index >= 0 && index < size()); + derived().template writePacket<StoreMode>(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<typename Derived> -template<typename OtherDerived> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyCoeff(int row, int col, const DenseBase<OtherDerived>& 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 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<typename Derived> -template<typename OtherDerived> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyCoeff(int index, const DenseBase<OtherDerived>& other) -{ - ei_internal_assert(index >= 0 && index < size()); - derived().coeffRef(index) = other.derived().coeff(index); -} - -template<typename Derived> -template<typename OtherDerived> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyCoeffByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& 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 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<typename Derived> -template<typename OtherDerived, int StoreMode, int LoadMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyPacket(int row, int col, const DenseBase<OtherDerived>& other) -{ - ei_internal_assert(row >= 0 && row < rows() - && col >= 0 && col < cols()); - derived().template writePacket<StoreMode>(row, col, - other.derived().template packet<LoadMode>(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<typename Derived> -template<typename OtherDerived, int StoreMode, int LoadMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyPacket(int index, const DenseBase<OtherDerived>& other) -{ - ei_internal_assert(index >= 0 && index < size()); - derived().template writePacket<StoreMode>(index, - other.derived().template packet<LoadMode>(index)); -} - -template<typename Derived> -template<typename OtherDerived, int StoreMode, int LoadMode> -EIGEN_STRONG_INLINE void DenseBase<Derived>::copyPacketByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& 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<OtherDerived, StoreMode, LoadMode>(row, col, other); -} + /** \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<typename OtherDerived> + EIGEN_STRONG_INLINE void copyCoeff(int row, int col, const DenseBase<OtherDerived>& 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 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<typename OtherDerived> + EIGEN_STRONG_INLINE void copyCoeff(int index, const DenseBase<OtherDerived>& other) + { + ei_internal_assert(index >= 0 && index < size()); + derived().coeffRef(index) = other.derived().coeff(index); + } + + + template<typename OtherDerived> + EIGEN_STRONG_INLINE void copyCoeffByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& 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<typename OtherDerived, int StoreMode, int LoadMode> + EIGEN_STRONG_INLINE void copyPacket(int row, int col, const DenseBase<OtherDerived>& other) + { + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + derived().template writePacket<StoreMode>(row, col, + other.derived().template packet<LoadMode>(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<typename OtherDerived, int StoreMode, int LoadMode> + EIGEN_STRONG_INLINE void copyPacket(int index, const DenseBase<OtherDerived>& other) + { + ei_internal_assert(index >= 0 && index < size()); + derived().template writePacket<StoreMode>(index, + other.derived().template packet<LoadMode>(index)); + } + + template<typename OtherDerived, int StoreMode, int LoadMode> + EIGEN_STRONG_INLINE void copyPacketByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& 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<OtherDerived, StoreMode, LoadMode>(row, col, other); + } +#endif +}; template<typename Derived, bool JustReturnZero> struct ei_first_aligned_impl { - inline static int run(const DenseBase<Derived>&) + inline static int run(const Derived&) { return 0; } }; template<typename Derived> struct ei_first_aligned_impl<Derived, false> { - inline static int run(const DenseBase<Derived>& 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<Derived, false> * documentation. */ template<typename Derived> -inline static int ei_first_aligned(const DenseBase<Derived>& m) +inline static int ei_first_aligned(const Derived& m) { return ei_first_aligned_impl - <Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)> - ::run(m); + <Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)> + ::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<typename Derived> class DenseBase : public ei_special_scalar_op_base<Derived,typename ei_traits<Derived>::Scalar, typename NumTraits<typename ei_traits<Derived>::Scalar>::Real> #else - : public EigenBase<Derived> + : public DenseCoeffsBase<Derived> #endif // not EIGEN_PARSED_BY_DOXYGEN { public: @@ -76,9 +76,33 @@ template<typename Derived> class DenseBase typedef typename ei_traits<Derived>::Scalar Scalar; typedef typename ei_packet_traits<Scalar>::type PacketScalar; + typedef DenseCoeffsBase<Derived> 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>::derived; - using EigenBase<Derived>::const_cast_derived; #endif // not EIGEN_PARSED_BY_DOXYGEN enum { @@ -172,13 +196,6 @@ template<typename Derived> class DenseBase typedef typename NumTraits<Scalar>::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<typename Derived> 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<typename OtherDerived> Derived& operator=(const DenseBase<OtherDerived>& other); @@ -343,56 +351,6 @@ template<typename Derived> class DenseBase template<typename OtherDerived> CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& 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<typename OtherDerived> - void copyCoeff(int row, int col, const DenseBase<OtherDerived>& other); - template<typename OtherDerived> - void copyCoeffByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& other); - template<typename OtherDerived> - void copyCoeff(int index, const DenseBase<OtherDerived>& other); - template<typename OtherDerived, int StoreMode, int LoadMode> - void copyPacket(int row, int col, const DenseBase<OtherDerived>& other); - template<typename OtherDerived, int StoreMode, int LoadMode> - void copyPacketByOuterInner(int outer, int inner, const DenseBase<OtherDerived>& other); - template<typename OtherDerived, int StoreMode, int LoadMode> - void copyPacket(int index, const DenseBase<OtherDerived>& other); - - private: - static int rowIndexByOuterInner(int outer, int inner); - static int colIndexByOuterInner(int outer, int inner); - public: -#endif // not EIGEN_PARSED_BY_DOXYGEN - - template<int LoadMode> - PacketScalar packet(int row, int col) const; - template<int LoadMode> - PacketScalar packetByOuterInner(int outer, int inner) const; - template<int StoreMode> - void writePacket(int row, int col, const PacketScalar& x); - template<int StoreMode> - void writePacketByOuterInner(int outer, int inner, const PacketScalar& x); - - template<int LoadMode> - PacketScalar packet(int index) const; - template<int StoreMode> - void writePacket(int index, const PacketScalar& x); - Eigen::Transpose<Derived> transpose(); const Eigen::Transpose<Derived> 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<typename Derived> 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<typename Dest> 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<typename T> struct ei_traits; template<typename T> struct NumTraits; +template<typename Derived> struct ei_has_direct_access +{ + enum { ret = (ei_traits<Derived>::Flags & DirectAccessBit) ? 1 : 0 }; +}; + template<typename Derived> struct EigenBase; +template<typename Derived> struct DenseBase; +template<typename Derived, bool EnableDirectAccessAPI = ei_has_direct_access<Derived>::ret> +class DenseCoeffsBase; template<typename _Scalar, int _Rows, int _Cols, int _Options = AutoAlign | @@ -49,14 +57,6 @@ template<typename ExpressionType> class NestByValue; template<typename ExpressionType> class ForceAlignedAccess; template<typename ExpressionType> class SwapWrapper; -// MSVC has a big bug: when the expression ei_traits<MatrixType>::Flags&DirectAccessBit ? 1 : 0 -// is used as default template parameter value here, it gets mis-evaluated as just ei_traits<MatrixType>::Flags -// Moreover, adding brackets tends to give compilation errors with MSVC. -// Solution: defer that to a helper struct. -template<typename Derived> struct ei_has_direct_access -{ - enum { ret = (ei_traits<Derived>::Flags & DirectAccessBit) ? 1 : 0 }; -}; template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool HasDirectAccess = ei_has_direct_access<XprType>::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<Derived, ArrayXpr> * overloads for complex types */ template<typename Derived,typename Scalar,typename OtherScalar, bool EnableIt = !ei_is_same_type<Scalar,OtherScalar>::ret > -struct ei_special_scalar_op_base : public EigenBase<Derived> +struct ei_special_scalar_op_base : public DenseCoeffsBase<Derived> { // 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<Derived> }; template<typename Derived,typename Scalar,typename OtherScalar> -struct ei_special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public EigenBase<Derived> +struct ei_special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCoeffsBase<Derived> { const CwiseUnaryOp<ei_scalar_multiple2_op<Scalar,OtherScalar>, 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<typename MatrixType> void basicStuffComplex(const MatrixType& m) VERIFY(!static_cast<const MatrixType&>(cm).imag().isZero()); } +#ifdef EIGEN_TEST_PART_2 void casting() { Matrix4f m = Matrix4f::Random(), m2; @@ -160,6 +161,7 @@ void casting() m2 = m.cast<float>(); // check the specialization when NewType == Type VERIFY(m.isApprox(m2)); } +#endif void test_basicstuff() { |