diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 96451a9e7..017331ccb 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -499,7 +499,8 @@ EIGEN_STRONG_INLINE Derived& DenseBase enum{ SameType = internal::is_same::value }; - + + EIGEN_STATIC_ASSERT_LVALUE(Derived) EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived) EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index bdd1291cf..1d7ceb9a0 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -501,8 +501,6 @@ template class DenseBase * Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down */ #ifdef EIGEN_INTERNAL_DEBUGGING - EIGEN_STATIC_ASSERT(internal::are_flags_consistent::ret, - INVALID_MATRIXBASE_TEMPLATE_PARAMETERS) EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor)) && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, int(!IsRowMajor))), INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION) diff --git a/Eigen/src/Core/DenseCoeffsBase.h b/Eigen/src/Core/DenseCoeffsBase.h index 13c93c392..ddc834304 100644 --- a/Eigen/src/Core/DenseCoeffsBase.h +++ b/Eigen/src/Core/DenseCoeffsBase.h @@ -554,19 +554,90 @@ class DenseCoeffsBase : public DenseCoeffsBase which defines functions to access entries using + * inherits DenseCoeffsBase which defines functions to access entries read-only using * \c operator() . * * \sa \ref TopicClassHierarchy */ template -class DenseCoeffsBase : public DenseCoeffsBase +class DenseCoeffsBase : public DenseCoeffsBase +{ + public: + + typedef DenseCoeffsBase Base; + typedef typename internal::traits::Index Index; + typedef typename internal::traits::Scalar Scalar; + typedef typename NumTraits::Real RealScalar; + + using Base::rows; + using Base::cols; + using Base::size; + using Base::derived; + + /** \returns the pointer increment between two consecutive elements within a slice in the inner direction. + * + * \sa outerStride(), rowStride(), colStride() + */ + inline Index innerStride() const + { + return derived().innerStride(); + } + + /** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns + * in a column-major matrix). + * + * \sa innerStride(), rowStride(), colStride() + */ + inline Index outerStride() const + { + return derived().outerStride(); + } + + // FIXME shall we remove it ? + inline Index stride() const + { + return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); + } + + /** \returns the pointer increment between two consecutive rows. + * + * \sa innerStride(), outerStride(), colStride() + */ + inline Index rowStride() const + { + return Derived::IsRowMajor ? outerStride() : innerStride(); + } + + /** \returns the pointer increment between two consecutive columns. + * + * \sa innerStride(), outerStride(), rowStride() + */ + inline Index colStride() const + { + return Derived::IsRowMajor ? innerStride() : outerStride(); + } +}; + +/** \brief Base class providing direct read/write coefficient access to matrices and arrays. + * \ingroup Core_Module + * \tparam Derived Type of the derived class + * \tparam DirectAccessors Constant indicating direct access + * + * This class defines functions to work with strides which can be used to access entries directly. This class + * inherits DenseCoeffsBase which defines functions to access entries read/write using + * \c operator(). + * + * \sa \ref TopicClassHierarchy + */ +template +class DenseCoeffsBase + : public DenseCoeffsBase { public: diff --git a/Eigen/src/Core/Map.h b/Eigen/src/Core/Map.h index d163e371a..0321f6669 100644 --- a/Eigen/src/Core/Map.h +++ b/Eigen/src/Core/Map.h @@ -80,8 +80,9 @@ namespace internal { template struct traits > - : public traits + : public traits::type> { + typedef traits::type> TraitsBase; typedef typename PlainObjectType::Index Index; typedef typename PlainObjectType::Scalar Scalar; enum { @@ -101,13 +102,15 @@ struct traits > || HasNoOuterStride || ( OuterStrideAtCompileTime!=Dynamic && ((static_cast(sizeof(Scalar))*OuterStrideAtCompileTime)%16)==0 ) ), - Flags0 = traits::Flags, + Flags0 = TraitsBase::Flags, Flags1 = IsAligned ? (int(Flags0) | AlignedBit) : (int(Flags0) & ~AlignedBit), - Flags2 = HasNoStride ? int(Flags1) : int(Flags1 & ~LinearAccessBit), - Flags = KeepsPacketAccess ? int(Flags2) : (int(Flags2) & ~PacketAccessBit) + Flags2 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime)) + ? int(Flags1) : int(Flags1 & ~LinearAccessBit), + Flags3 = internal::is_const::value ? (int(Flags2) & ~LvalueBit) : int(Flags2), + Flags = KeepsPacketAccess ? int(Flags3) : (int(Flags3) & ~PacketAccessBit) }; private: - enum { Options }; // Expressions don't support Options + enum { Options }; // Expressions don't have Options }; } @@ -120,6 +123,9 @@ template class Ma EIGEN_DENSE_PUBLIC_INTERFACE(Map) + typedef typename Base::PointerType PointerType; + + inline Index innerStride() const { return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; @@ -138,7 +144,7 @@ template class Ma * \param data pointer to the array to map * \param stride optional Stride object, passing the strides. */ - inline Map(const Scalar* data, const StrideType& stride = StrideType()) + inline Map(PointerType data, const StrideType& stride = StrideType()) : Base(data), m_stride(stride) { PlainObjectType::Base::_check_template_params(); @@ -150,7 +156,7 @@ template class Ma * \param size the size of the vector expression * \param stride optional Stride object, passing the strides. */ - inline Map(const Scalar* data, Index size, const StrideType& stride = StrideType()) + inline Map(PointerType data, Index size, const StrideType& stride = StrideType()) : Base(data, size), m_stride(stride) { PlainObjectType::Base::_check_template_params(); @@ -163,7 +169,7 @@ template class Ma * \param cols the number of columns of the matrix expression * \param stride optional Stride object, passing the strides. */ - inline Map(const Scalar* data, Index rows, Index cols, const StrideType& stride = StrideType()) + inline Map(PointerType data, Index rows, Index cols, const StrideType& stride = StrideType()) : Base(data, rows, cols), m_stride(stride) { PlainObjectType::Base::_check_template_params(); diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index 5fab85ed7..435d9c09d 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -26,6 +26,11 @@ #ifndef EIGEN_MAPBASE_H #define EIGEN_MAPBASE_H +#define EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) \ + EIGEN_STATIC_ASSERT(int(internal::traits::Flags) & LinearAccessBit, \ + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT) + + /** \class MapBase * \ingroup Core_Module * @@ -33,7 +38,7 @@ * * \sa class Map, class Block */ -template class MapBase +template class MapBase : public internal::dense_xpr_base::type { public: @@ -45,12 +50,16 @@ template class MapBase SizeAtCompileTime = Base::SizeAtCompileTime }; - typedef typename internal::traits::StorageKind StorageKind; typedef typename internal::traits::Index Index; typedef typename internal::traits::Scalar Scalar; typedef typename internal::packet_traits::type PacketScalar; typedef typename NumTraits::Real RealScalar; + typedef typename internal::conditional< + int(internal::traits::Flags) & LvalueBit, + Scalar *, + const Scalar *>::type + PointerType; using Base::derived; // using Base::RowsAtCompileTime; @@ -63,10 +72,6 @@ template class MapBase using Base::Flags; using Base::IsRowMajor; - using Base::CoeffReadCost; - -// using Base::derived; - using Base::const_cast_derived; using Base::rows; using Base::cols; using Base::size; @@ -74,11 +79,6 @@ template class MapBase using Base::coeffRef; using Base::lazyAssign; using Base::eval; -// using Base::operator=; - using Base::operator+=; - using Base::operator-=; - using Base::operator*=; - using Base::operator/=; using Base::innerStride; using Base::outerStride; @@ -98,28 +98,27 @@ template class MapBase * \sa innerStride(), outerStride() */ inline const Scalar* data() const { return m_data; } - inline Scalar* data() { return const_cast(m_data); } inline const Scalar& coeff(Index row, Index col) const { return m_data[col * colStride() + row * rowStride()]; } - inline Scalar& coeffRef(Index row, Index col) - { - return const_cast(m_data)[col * colStride() + row * rowStride()]; - } - inline const Scalar& coeff(Index index) const { - eigen_assert(Derived::IsVectorAtCompileTime || (internal::traits::Flags & LinearAccessBit)); + EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) return m_data[index * innerStride()]; } - inline Scalar& coeffRef(Index index) + inline const Scalar& coeffRef(Index row, Index col) const { - eigen_assert(Derived::IsVectorAtCompileTime || (internal::traits::Flags & LinearAccessBit)); - return const_cast(m_data)[index * innerStride()]; + return this->m_data[col * colStride() + row * rowStride()]; + } + + inline const Scalar& coeffRef(Index index) const + { + EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) + return this->m_data[index * innerStride()]; } template @@ -132,30 +131,17 @@ template class MapBase template inline PacketScalar packet(Index index) const { + EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) return internal::ploadt(m_data + index * innerStride()); } - template - inline void writePacket(Index row, Index col, const PacketScalar& x) - { - internal::pstoret - (const_cast(m_data) + (col * colStride() + row * rowStride()), x); - } - - template - inline void writePacket(Index index, const PacketScalar& x) - { - internal::pstoret - (const_cast(m_data) + index * innerStride(), x); - } - - inline MapBase(const Scalar* data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) + inline MapBase(PointerType data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) checkSanity(); } - inline MapBase(const Scalar* data, Index size) + inline MapBase(PointerType data, Index size) : m_data(data), m_rows(RowsAtCompileTime == Dynamic ? size : Index(RowsAtCompileTime)), m_cols(ColsAtCompileTime == Dynamic ? size : Index(ColsAtCompileTime)) @@ -166,7 +152,7 @@ template class MapBase checkSanity(); } - inline MapBase(const Scalar* data, Index rows, Index cols) + inline MapBase(PointerType data, Index rows, Index cols) : m_data(data), m_rows(rows), m_cols(cols) { eigen_assert( (data == 0) @@ -175,14 +161,6 @@ template class MapBase checkSanity(); } - Derived& operator=(const MapBase& other) - { - Base::operator=(other); - return derived(); - } - - using Base::operator=; - protected: void checkSanity() const @@ -194,9 +172,76 @@ template class MapBase && "data is not aligned"); } - const Scalar* EIGEN_RESTRICT m_data; + PointerType EIGEN_RESTRICT m_data; const internal::variable_if_dynamic m_rows; const internal::variable_if_dynamic m_cols; }; +template class MapBase + : public MapBase +{ + public: + + typedef MapBase Base; + + typedef typename Base::Scalar Scalar; + typedef typename Base::PacketScalar PacketScalar; + typedef typename Base::Index Index; + typedef typename Base::PointerType PointerType; + + using Base::derived; + using Base::rows; + using Base::cols; + using Base::size; + using Base::coeff; + using Base::coeffRef; + + using Base::innerStride; + using Base::outerStride; + using Base::rowStride; + using Base::colStride; + + inline const Scalar* data() const { return this->m_data; } + inline Scalar* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error + + inline Scalar& coeffRef(Index row, Index col) + { + return this->m_data[col * colStride() + row * rowStride()]; + } + + inline Scalar& coeffRef(Index index) + { + EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) + return this->m_data[index * innerStride()]; + } + + template + inline void writePacket(Index row, Index col, const PacketScalar& x) + { + internal::pstoret + (this->m_data + (col * colStride() + row * rowStride()), x); + } + + template + inline void writePacket(Index index, const PacketScalar& x) + { + EIGEN_STATIC_ASSERT_LINEAR_ACCESS(Derived) + internal::pstoret + (this->m_data + index * innerStride(), x); + } + + inline MapBase(PointerType data) : Base(data) {} + inline MapBase(PointerType data, Index size) : Base(data, size) {} + inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {} + + Derived& operator=(const MapBase& other) + { + Base::Base::operator=(other); + return derived(); + } + + using Base::Base::operator=; +}; + + #endif // EIGEN_MAPBASE_H diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h index 6bb42f1c9..4df262d16 100644 --- a/Eigen/src/Core/PlainObjectBase.h +++ b/Eigen/src/Core/PlainObjectBase.h @@ -66,10 +66,15 @@ class PlainObjectBase : public internal::dense_xpr_base::type using Base::IsVectorAtCompileTime; using Base::Flags; + typedef typename internal::add_const::type ConstDerived; friend class Eigen::Map; - typedef class Eigen::Map UnalignedMapType; + typedef class Eigen::Map MapType; + friend class Eigen::Map; + typedef class Eigen::Map ConstMapType; friend class Eigen::Map; - typedef class Eigen::Map AlignedMapType; + typedef class Eigen::Map AlignedMapType; + friend class Eigen::Map; + typedef class Eigen::Map ConstAlignedMapType; protected: DenseStorage m_storage; @@ -376,29 +381,29 @@ class PlainObjectBase : public internal::dense_xpr_base::type * \see class Map */ //@{ - inline static const UnalignedMapType Map(const Scalar* data) - { return UnalignedMapType(data); } - inline static UnalignedMapType Map(Scalar* data) - { return UnalignedMapType(data); } - inline static const UnalignedMapType Map(const Scalar* data, Index size) - { return UnalignedMapType(data, size); } - inline static UnalignedMapType Map(Scalar* data, Index size) - { return UnalignedMapType(data, size); } - inline static const UnalignedMapType Map(const Scalar* data, Index rows, Index cols) - { return UnalignedMapType(data, rows, cols); } - inline static UnalignedMapType Map(Scalar* data, Index rows, Index cols) - { return UnalignedMapType(data, rows, cols); } + inline static const ConstMapType Map(const Scalar* data) + { return ConstMapType(data); } + inline static MapType Map(Scalar* data) + { return MapType(data); } + inline static const ConstMapType Map(const Scalar* data, Index size) + { return ConstMapType(data, size); } + inline static MapType Map(Scalar* data, Index size) + { return MapType(data, size); } + inline static const ConstMapType Map(const Scalar* data, Index rows, Index cols) + { return ConstMapType(data, rows, cols); } + inline static MapType Map(Scalar* data, Index rows, Index cols) + { return MapType(data, rows, cols); } - inline static const AlignedMapType MapAligned(const Scalar* data) - { return AlignedMapType(data); } + inline static const ConstAlignedMapType MapAligned(const Scalar* data) + { return ConstAlignedMapType(data); } inline static AlignedMapType MapAligned(Scalar* data) { return AlignedMapType(data); } - inline static const AlignedMapType MapAligned(const Scalar* data, Index size) - { return AlignedMapType(data, size); } + inline static const ConstAlignedMapType MapAligned(const Scalar* data, Index size) + { return ConstAlignedMapType(data, size); } inline static AlignedMapType MapAligned(Scalar* data, Index size) { return AlignedMapType(data, size); } - inline static const AlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) - { return AlignedMapType(data, rows, cols); } + inline static const ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) + { return ConstAlignedMapType(data, rows, cols); } inline static AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) { return AlignedMapType(data, rows, cols); } //@} diff --git a/Eigen/src/Core/SelfAdjointView.h b/Eigen/src/Core/SelfAdjointView.h index 564895143..dd1757aea 100644 --- a/Eigen/src/Core/SelfAdjointView.h +++ b/Eigen/src/Core/SelfAdjointView.h @@ -80,7 +80,7 @@ template class SelfAdjointView typedef typename MatrixType::PlainObject PlainObject; inline SelfAdjointView(const MatrixType& matrix) : m_matrix(matrix) - { eigen_assert(internal::are_flags_consistent::ret); } + {} inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h index ba0f2741e..328aac611 100644 --- a/Eigen/src/Core/TriangularMatrix.h +++ b/Eigen/src/Core/TriangularMatrix.h @@ -181,7 +181,7 @@ template class TriangularView }; inline TriangularView(const MatrixType& matrix) : m_matrix(matrix) - { eigen_assert(internal::are_flags_consistent::ret); } + {} inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } diff --git a/Eigen/src/Core/products/SelfadjointProduct.h b/Eigen/src/Core/products/SelfadjointProduct.h index c6a5287b5..0bf5b72fc 100644 --- a/Eigen/src/Core/products/SelfadjointProduct.h +++ b/Eigen/src/Core/products/SelfadjointProduct.h @@ -53,7 +53,7 @@ SelfAdjointView& SelfAdjointView MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor, UpLo> ::run(_expression().cols(), actualU.cols(), &actualU.coeff(0,0), actualU.outerStride(), &actualU.coeff(0,0), actualU.outerStride(), - const_cast(_expression().data()), _expression().outerStride(), actualAlpha); + _expression().const_cast_derived().data(), _expression().outerStride(), actualAlpha); return *this; } diff --git a/Eigen/src/Core/products/SelfadjointRank2Update.h b/Eigen/src/Core/products/SelfadjointRank2Update.h index d81c568b7..7d91f04a5 100644 --- a/Eigen/src/Core/products/SelfadjointRank2Update.h +++ b/Eigen/src/Core/products/SelfadjointRank2Update.h @@ -91,7 +91,7 @@ SelfAdjointView& SelfAdjointView typename internal::remove_all::type>::type, typename internal::remove_all::type>::type, (IsRowMajor ? int(UpLo==Upper ? Lower : Upper) : UpLo)> - ::run(const_cast(_expression().data()),_expression().outerStride(),actualU,actualV,actualAlpha); + ::run(_expression().const_cast_derived().data(),_expression().outerStride(),actualU,actualV,actualAlpha); return *this; } diff --git a/Eigen/src/Core/products/TriangularMatrixVector.h b/Eigen/src/Core/products/TriangularMatrixVector.h index 894a42b6c..3694be73a 100644 --- a/Eigen/src/Core/products/TriangularMatrixVector.h +++ b/Eigen/src/Core/products/TriangularMatrixVector.h @@ -46,11 +46,11 @@ struct product_triangular_matrix_vector, 0, OuterStride<> > LhsMap; + typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride)); typename conj_expr_if::type cjLhs(lhs); - typedef Map, 0, InnerStride<> > RhsMap; + typedef Map, 0, InnerStride<> > RhsMap; const RhsMap rhs(_rhs,cols,InnerStride<>(rhsIncr)); typename conj_expr_if::type cjRhs(rhs); @@ -100,11 +100,11 @@ struct product_triangular_matrix_vector, 0, OuterStride<> > LhsMap; + typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride)); typename conj_expr_if::type cjLhs(lhs); - typedef Map > RhsMap; + typedef Map > RhsMap; const RhsMap rhs(_rhs,cols); typename conj_expr_if::type cjRhs(rhs); diff --git a/Eigen/src/Core/products/TriangularSolverVector.h b/Eigen/src/Core/products/TriangularSolverVector.h index 16184abb5..0342bb356 100644 --- a/Eigen/src/Core/products/TriangularSolverVector.h +++ b/Eigen/src/Core/products/TriangularSolverVector.h @@ -48,7 +48,7 @@ struct triangular_solve_vector, 0, OuterStride<> > LhsMap; + typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,size,size,OuterStride<>(lhsStride)); typename internal::conditional< Conjugate, @@ -84,7 +84,7 @@ struct triangular_solve_vector0) - rhs[i] -= (cjLhs.row(i).segment(s,k).transpose().cwiseProduct(Map >(rhs+s,k))).sum(); + rhs[i] -= (cjLhs.row(i).segment(s,k).transpose().cwiseProduct(Map >(rhs+s,k))).sum(); if(!(Mode & UnitDiag)) rhs[i] /= cjLhs(i,i); @@ -102,7 +102,7 @@ struct triangular_solve_vector, 0, OuterStride<> > LhsMap; + typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,size,size,OuterStride<>(lhsStride)); typename internal::conditional,LhsMap>, diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 99b4f3319..03cadc107 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -128,8 +128,10 @@ const unsigned int LinearAccessBit = 0x10; * Means the expression has a coeffRef() method, i.e. is writable as its individual coefficients are directly addressable. * This rules out read-only expressions. * - * Note that DirectAccessBit implies LvalueBit, but the converse is false: LvalueBit doesn't imply DirectAccessBit because - * DirectAccessBit means that the whole memory layout is a plain strided array. + * Note that DirectAccessBit and LvalueBit are mutually orthogonal, as there are examples of expression having one but note + * the other: + * \li writable expressions that don't have a very simple memory layout as a strided array, have LvalueBit but not DirectAccessBit + * \li Map-to-const expressions, for example Map, have DirectAccessBit but not LvalueBit * * Expressions having LvalueBit also have their coeff() method returning a const reference instead of returning a new value. */ @@ -137,14 +139,12 @@ const unsigned int LvalueBit = 0x20; /** \ingroup flags * - * Means that the underlying array of coefficients can be directly accessed. This means two things. - * - * First, this means LvalueBit, i.e. this means that the expression has a coeffRef() method, i.e. is writable as its - * individual coefficients are directly addressable. This rules out read-only expressions. - * - * Second, the memory layout of the array of coefficients must be exactly the natural one suggested by rows(), cols(), + * Means that the underlying array of coefficients can be directly accessed as a plain strided array. The memory layout + * of the array of coefficients must be exactly the natural one suggested by rows(), cols(), * outerStride(), innerStride(), and the RowMajorBit. This rules out expressions such as Diagonal, whose coefficients, * though referencable, do not have such a regular memory layout. + * + * See the comment on LvalueBit for an explanation of how LvalueBit and DirectAccessBit are mutually orthogonal. */ const unsigned int DirectAccessBit = 0x40; @@ -242,7 +242,7 @@ enum { }; enum AccessorLevels { - ReadOnlyAccessors, WriteAccessors, DirectAccessors + ReadOnlyAccessors, WriteAccessors, DirectAccessors, DirectWriteAccessors }; enum DecompositionOptions { diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 0d0b905ea..c84401fa8 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -33,16 +33,26 @@ template struct has_direct_access { enum { ret = (traits::Flags & DirectAccessBit) ? 1 : 0 }; }; + +template struct accessors_level +{ + enum { has_direct_access = (traits::Flags & DirectAccessBit) ? 1 : 0, + has_write_access = (traits::Flags & LvalueBit) ? 1 : 0, + value = has_direct_access ? (has_write_access ? DirectWriteAccessors : DirectAccessors) + : (has_write_access ? WriteAccessors : ReadOnlyAccessors) + }; +}; + } // end namespace internal template struct NumTraits; template struct EigenBase; template class DenseBase; + + template::Flags & DirectAccessBit) ? DirectAccessors - : (internal::traits::Flags & LvalueBit) ? WriteAccessors - : ReadOnlyAccessors> + int Level = internal::accessors_level::value > class DenseCoeffsBase; template class Diagonal; template class PermutationMatrix; template class Transpositions; +template::has_write_access ? WriteAccessors : ReadOnlyAccessors +> class MapBase; template class Stride; template > class Map; diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index dbdf8b209..3637b7c0a 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -93,6 +93,8 @@ THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS, YOU_CANNOT_MIX_ARRAYS_AND_MATRICES, YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION, + YOU_ARE_TRYING_TO_WRITE_INTO_A_READ_ONLY_EXPRESSION, + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT, THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS }; }; @@ -183,4 +185,8 @@ (TYPE::ColsAtCompileTime == 1 || TYPE::ColsAtCompileTime == Dynamic), \ THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS) +#define EIGEN_STATIC_ASSERT_LVALUE(Derived) \ + EIGEN_STATIC_ASSERT(int(internal::traits::Flags) & LvalueBit, \ + YOU_ARE_TRYING_TO_WRITE_INTO_A_READ_ONLY_EXPRESSION) + #endif // EIGEN_STATIC_ASSERT_H diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index ea43aa91e..46ade2ba1 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -333,11 +333,6 @@ template::type> str >::type type; }; -template struct are_flags_consistent -{ - enum { ret = EIGEN_IMPLIES(bool(Flags&DirectAccessBit), bool(Flags&LvalueBit)) }; -}; - template::XprKind> struct dense_xpr_base { diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index afbeef26c..2c4098fc1 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -298,6 +298,42 @@ traits > }; } +/** \brief Quaternion expression mapping a constant memory buffer + * + * \param _Scalar the type of the Quaternion coefficients + * \param PacketAccess see class Map + * + * This is a specialization of class Map for Quaternion. This class allows to view + * a 4 scalar memory buffer as an Eigen's Quaternion object. + * + * \sa class Map, class Quaternion, class QuaternionBase + */ +template +class Map, PacketAccess > + : public QuaternionBase, PacketAccess> > +{ + typedef QuaternionBase, PacketAccess> > Base; + + public: + typedef _Scalar Scalar; + typedef typename internal::traits::Coefficients Coefficients; + EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map) + using Base::operator*=; + + /** Constructs a Mapped Quaternion object from the pointer \a coeffs + * + * The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order: + * \code *coeffs == {x, y, z, w} \endcode + * + * If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */ + EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {} + + inline const Coefficients& coeffs() const { return m_coeffs;} + + protected: + const Coefficients m_coeffs; +}; + /** \brief Expression of a quaternion from a memory buffer * * \param _Scalar the type of the Quaternion coefficients @@ -326,10 +362,10 @@ class Map, PacketAccess > * \code *coeffs == {x, y, z, w} \endcode * * If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */ - EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {} + EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {} - inline Coefficients& coeffs() { return m_coeffs;} - inline const Coefficients& coeffs() const { return m_coeffs;} + inline Coefficients& coeffs() { return m_coeffs; } + inline const Coefficients& coeffs() const { return m_coeffs; } protected: Coefficients m_coeffs; diff --git a/Eigen/src/Sparse/SparseSelfAdjointView.h b/Eigen/src/Sparse/SparseSelfAdjointView.h index 60136e9f7..3749c604a 100644 --- a/Eigen/src/Sparse/SparseSelfAdjointView.h +++ b/Eigen/src/Sparse/SparseSelfAdjointView.h @@ -75,7 +75,6 @@ template class SparseSelfAdjointView inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix) { - eigen_assert(internal::are_flags_consistent::ret); eigen_assert(rows()==cols() && "SelfAdjointView is only for squared matrices"); } diff --git a/test/map.cpp b/test/map.cpp index aa954167a..99f88b966 100644 --- a/test/map.cpp +++ b/test/map.cpp @@ -22,6 +22,10 @@ // License and a copy of the GNU General Public License along with // Eigen. If not, see . +#ifndef EIGEN_NO_STATIC_ASSERT +#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them +#endif + #include "main.h" template void map_class_vector(const VectorType& m) @@ -110,15 +114,34 @@ template void map_static_methods(const VectorType& m) delete[] array3; } +template void check_const_correctness(const PlainObjectType&) +{ + typedef typename PlainObjectType::Index Index; + typedef typename PlainObjectType::Scalar Scalar; + + // there's a lot that we can't test here while still having this test compile! + // the only possible approach would be to run a script trying to compile stuff and checking that it fails. + // CMake can help with that. + + // verify that map-to-const don't have LvalueBit + typedef typename internal::add_const::type ConstPlainObjectType; + VERIFY( !(internal::traits >::Flags & LvalueBit) ); + VERIFY( !(internal::traits >::Flags & LvalueBit) ); + VERIFY( !(Map::Flags & LvalueBit) ); + VERIFY( !(Map::Flags & LvalueBit) ); +} void test_map() { for(int i = 0; i < g_repeat; i++) { CALL_SUBTEST_1( map_class_vector(Matrix()) ); + CALL_SUBTEST_1( check_const_correctness(Matrix()) ); CALL_SUBTEST_2( map_class_vector(Vector4d()) ); + CALL_SUBTEST_2( check_const_correctness(Matrix4d()) ); CALL_SUBTEST_3( map_class_vector(RowVector4f()) ); CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) ); CALL_SUBTEST_5( map_class_vector(VectorXi(12)) ); + CALL_SUBTEST_5( check_const_correctness(VectorXi(12)) ); CALL_SUBTEST_1( map_class_matrix(Matrix()) ); CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );