From b73e22905dd1544830b41463576d112c53fc66d9 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 18 Feb 2010 20:42:38 -0500 Subject: miserable half-working state, commiting to a fork just in case, just to perfect my day, my hard disk would die. Will write a more detailed commit message once it's working. --- Eigen/src/Core/Assign.h | 75 +++++++++++++-------- Eigen/src/Core/Block.h | 37 ++++++++--- Eigen/src/Core/DenseBase.h | 64 ++++++++++++------ Eigen/src/Core/DenseStorageBase.h | 8 +-- Eigen/src/Core/Map.h | 57 ++++++++++++---- Eigen/src/Core/MapBase.h | 94 ++++++++++++++++----------- Eigen/src/Core/Matrix.h | 8 ++- Eigen/src/Core/Product.h | 4 +- Eigen/src/Core/ReturnByValue.h | 11 +--- Eigen/src/Core/Transpose.h | 6 +- Eigen/src/Core/products/GeneralMatrixMatrix.h | 7 +- Eigen/src/Core/util/ForwardDeclarations.h | 7 +- Eigen/src/Core/util/StaticAssert.h | 7 +- Eigen/src/Core/util/XprHelper.h | 4 +- 14 files changed, 256 insertions(+), 133 deletions(-) (limited to 'Eigen/src') diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 9440cebf1..174fd0080 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -37,19 +37,20 @@ struct ei_assign_traits public: enum { DstIsAligned = Derived::Flags & AlignedBit, + DstHasDirectAccess = Derived::Flags & DirectAccessBit, SrcIsAligned = OtherDerived::Flags & AlignedBit, - SrcAlignment = DstIsAligned && SrcIsAligned ? Aligned : Unaligned + JointAlignment = DstIsAligned && SrcIsAligned ? Aligned : Unaligned }; private: enum { - InnerSize = int(Derived::Flags)&RowMajorBit - ? Derived::ColsAtCompileTime - : Derived::RowsAtCompileTime, - InnerMaxSize = int(Derived::Flags)&RowMajorBit - ? Derived::MaxColsAtCompileTime - : Derived::MaxRowsAtCompileTime, - MaxSizeAtCompileTime = ei_size_at_compile_time::ret, + InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime) + : int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime) + : int(Derived::RowsAtCompileTime), + InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime) + : int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime) + : int(Derived::MaxRowsAtCompileTime), + MaxSizeAtCompileTime = Derived::SizeAtCompileTime, PacketSize = ei_packet_traits::size }; @@ -60,11 +61,11 @@ private: MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0 && int(DstIsAligned) && int(SrcIsAligned), MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit), - MayLinearVectorize = MightVectorize && MayLinearize - && (DstIsAligned || MaxSizeAtCompileTime == Dynamic), + MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess + && (DstIsAligned || MaxSizeAtCompileTime == Dynamic), /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, so it's only good for large enough sizes. */ - MaySliceVectorize = MightVectorize && int(InnerMaxSize)>=3*PacketSize + MaySliceVectorize = MightVectorize && DstHasDirectAccess && int(InnerMaxSize)>=3*PacketSize /* slice vectorization can be slow, so we only want it if the slices are big, which is indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block in a fixed-size matrix */ @@ -108,12 +109,13 @@ public: { EIGEN_DEBUG_VAR(DstIsAligned) EIGEN_DEBUG_VAR(SrcIsAligned) - EIGEN_DEBUG_VAR(SrcAlignment) + EIGEN_DEBUG_VAR(JointAlignment) EIGEN_DEBUG_VAR(InnerSize) EIGEN_DEBUG_VAR(InnerMaxSize) EIGEN_DEBUG_VAR(PacketSize) EIGEN_DEBUG_VAR(StorageOrdersAgree) EIGEN_DEBUG_VAR(MightVectorize) + EIGEN_DEBUG_VAR(MayLinearize) EIGEN_DEBUG_VAR(MayInnerVectorize) EIGEN_DEBUG_VAR(MayLinearVectorize) EIGEN_DEBUG_VAR(MaySliceVectorize) @@ -211,12 +213,12 @@ struct ei_assign_innervec_CompleteUnrolling col = int(Derived1::Flags)&RowMajorBit ? Index % int(Derived1::ColsAtCompileTime) : Index / Derived1::RowsAtCompileTime, - SrcAlignment = ei_assign_traits::SrcAlignment + JointAlignment = ei_assign_traits::JointAlignment }; EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) { - dst.template copyPacket(row, col, src); + dst.template copyPacket(row, col, src); ei_assign_innervec_CompleteUnrolling::size, Stop>::run(dst, src); } @@ -265,16 +267,29 @@ struct ei_assign_impl { inline static void run(Derived1 &dst, const Derived2 &src) { - const int innerSize = dst.innerSize(); - const int outerSize = dst.outerSize(); - for(int j = 0; j < outerSize; ++j) - for(int i = 0; i < innerSize; ++i) - { - if(int(Derived1::Flags)&RowMajorBit) - dst.copyCoeff(j, i, src); - else - dst.copyCoeff(i, j, src); - } + if(Derived1::ColsAtCompileTime == 1) + { + for(int i = 0; i < dst.rows(); ++i) + dst.copyCoeff(i, 0, src); + } + else if(Derived1::RowsAtCompileTime == 1) + { + for(int i = 0; i < dst.cols(); ++i) + dst.copyCoeff(0, i, src); + } + else + { + const int innerSize = dst.innerSize(); + const int outerSize = dst.outerSize(); + for(int j = 0; j < outerSize; ++j) + for(int i = 0; i < innerSize; ++i) + { + if(int(Derived1::Flags)&RowMajorBit) + dst.copyCoeff(j, i, src); + else + dst.copyCoeff(i, j, src); + } + } } }; @@ -418,7 +433,7 @@ struct ei_assign_impl::SrcAlignment>(index, src); + dst.template copyPacket::JointAlignment>(index, src); } ei_unaligned_assign_impl<>::run(src,dst,alignedEnd,size); @@ -452,7 +467,7 @@ struct ei_assign_impl const int packetAlignedMask = packetSize - 1; const int innerSize = dst.innerSize(); const int outerSize = dst.outerSize(); - const int alignedStep = (packetSize - dst.stride() % packetSize) & packetAlignedMask; + const int alignedStep = (packetSize - dst.outerStride() % packetSize) & packetAlignedMask; int alignedStart = ei_assign_traits::DstIsAligned ? 0 : ei_first_aligned(&dst.coeffRef(0,0), innerSize); @@ -504,6 +519,14 @@ EIGEN_STRONG_INLINE Derived& DenseBase EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived) EIGEN_STATIC_ASSERT((ei_is_same_type::ret), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + if(Derived::ColsAtCompileTime == 1) + { + ei_assert(OtherDerived::RowsAtCompileTime == 1 || other.cols() == 1); + } + if(Derived::RowsAtCompileTime == 1) + { + ei_assert(OtherDerived::ColsAtCompileTime == 1 || other.rows() == 1); + } #ifdef EIGEN_DEBUG_ASSIGN ei_assign_traits::debug(); #endif diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index 3b4234c22..8a7aea91f 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -80,6 +80,20 @@ struct ei_traits > }; }; +template +struct ei_traits > : ei_traits > +{ + enum { + InnerStrideAtCompileTime = + (BlockRows==1 && !(int(MatrixType::Flags)&RowMajorBit)) + || (BlockCols==1 && (int(MatrixType::Flags)&RowMajorBit)) + ? MatrixType::OuterStrideAtCompileTime + : MatrixType::InnerStrideAtCompileTime, + OuterStrideAtCompileTime = + (BlockRows==1||BlockCols==1) ? 0 : MatrixType::OuterStrideAtCompileTime + }; +}; + template class Block : public MatrixType::template MakeBase< Block >::Type { @@ -196,8 +210,8 @@ template && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= matrix.cols()); } - /** \sa MapBase::stride() */ - inline int stride() const + /** \sa MapBase::innerStride() */ + inline int innerStride() const + { + return (RowsAtCompileTime==1 && !(int(MatrixType::Flags)&RowMajorBit)) + || (ColsAtCompileTime==1 && (int(MatrixType::Flags)&RowMajorBit)) + ? m_matrix.outerStride() + : m_matrix.innerStride(); + } + + /** \sa MapBase::outerStride() */ + inline int outerStride() const { - return ((!Base::IsVectorAtCompileTime) - || (BlockRows==1 && ((Flags&RowMajorBit)==0)) - || (BlockCols==1 && ((Flags&RowMajorBit)==RowMajorBit))) - ? m_matrix.stride() : 1; + return IsVectorAtCompileTime ? 0 : m_matrix.outerStride(); } #ifndef __SUNPRO_CC // FIXME sunstudio is not friendly with the above friend... + // META-FIXME there is no 'friend' keyword around here. Is this obsolete? protected: #endif diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 21d792f49..d8f789ae0 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -158,31 +158,60 @@ template class DenseBase * In other words, this function returns * \code rows()==1 || cols()==1 \endcode * \sa rows(), cols(), IsVectorAtCompileTime. */ - inline bool isVector() const { return rows()==1 || cols()==1; } - /** \returns the size of the storage major dimension, - * i.e., the number of columns for a columns major matrix, and the number of rows otherwise */ - int outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); } - /** \returns the size of the inner dimension according to the storage order, - * i.e., the number of rows for a columns major matrix, and the number of cols otherwise */ - int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); } - - /** Only plain matrices, not expressions may be resized; therefore the only useful resize method is - * Matrix::resize(). The present method only asserts that the new size equals the old size, and does + + /** \returns the outer size. + * + * \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension + * with respect to the storage order, i.e., the number of columns for a column-major matrix, + * and the number of rows for a row-major matrix. */ + int outerSize() const + { + return IsVectorAtCompileTime ? 1 + : (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); + } + + /** \returns the inner size. + * + * \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension + * with respect to the storage order, i.e., the number of rows for a column-major matrix, + * and the number of columns for a row-major matrix. */ + int innerSize() const + { + return IsVectorAtCompileTime ? this->size() + : (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); + } + + /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are + * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does * nothing else. */ void resize(int size) { ei_assert(size == this->size() - && "MatrixBase::resize() does not actually allow to resize."); + && "DenseBase::resize() does not actually allow to resize."); } - /** Only plain matrices, not expressions may be resized; therefore the only useful resize method is - * Matrix::resize(). The present method only asserts that the new size equals the old size, and does + /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are + * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does * nothing else. */ void resize(int rows, int cols) { ei_assert(rows == this->rows() && cols == this->cols() - && "MatrixBase::resize() does not actually allow to resize."); + && "DenseBase::resize() does not actually allow to resize."); + } + + int innerStride() const + { + EIGEN_STATIC_ASSERT(int(Flags)&DirectAccessBit, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES) + return derived().innerStride(); + } + + int outerStride() const + { + EIGEN_STATIC_ASSERT(int(Flags)&DirectAccessBit, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES) + return derived().outerStride(); } #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -407,13 +436,6 @@ template class DenseBase template void swap(DenseBase EIGEN_REF_TO_TEMPORARY other); - /** \returns number of elements to skip to pass from one row (resp. column) to another - * for a row-major (resp. column-major) matrix. - * Combined with coeffRef() and the \ref flags flags, it allows a direct access to the data - * of the underlying matrix. - */ - inline int stride() const { return derived().stride(); } - inline const NestByValue nestByValue() const; inline const ForceAlignedAccess forceAlignedAccess() const; inline ForceAlignedAccess forceAlignedAccess(); diff --git a/Eigen/src/Core/DenseStorageBase.h b/Eigen/src/Core/DenseStorageBase.h index 5c8e48768..04dfb1176 100644 --- a/Eigen/src/Core/DenseStorageBase.h +++ b/Eigen/src/Core/DenseStorageBase.h @@ -253,13 +253,13 @@ class DenseStorageBase : public _Base { if(RowsAtCompileTime == 1) { - ei_assert(other.isVector()); - resize(1, other.size()); + ei_assert(other.rows() == 1); + resize(1, other.cols()); } else if(ColsAtCompileTime == 1) { - ei_assert(other.isVector()); - resize(other.size(), 1); + ei_assert(other.cols() == 1); + resize(other.rows(), 1); } else resize(other.rows(), other.cols()); } diff --git a/Eigen/src/Core/Map.h b/Eigen/src/Core/Map.h index 83688dbca..432bf1661 100644 --- a/Eigen/src/Core/Map.h +++ b/Eigen/src/Core/Map.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or @@ -48,32 +48,59 @@ * * \sa Matrix::Map() */ -template -struct ei_traits > : public ei_traits +template +struct ei_traits > + : public ei_traits { enum { - Flags = (Options&Aligned)==Aligned ? ei_traits::Flags | AlignedBit - : ei_traits::Flags & ~AlignedBit - }; + Flags0 = ei_traits::Flags, + Flags1 = ((Options&Aligned)==Aligned ? Flags0 | AlignedBit + : Flags0 & ~AlignedBit), + Flags = int(StrideType::InnerStrideAtCompileTime)==1 ? Flags1 : (Flags1 & ~PacketAccessBit), + InnerStrideAtCompileTime = int(StrideType::InnerStrideAtCompileTime) != 0 ? int(StrideType::InnerStrideAtCompileTime) : 1, + OuterStrideAtCompileTime = + int(StrideType::OuterStrideAtCompileTime != 0) ? int(StrideType::OuterStrideAtCompileTime) + : int(MatrixType::IsVectorAtCompileTime) ? int(MatrixType::SizeAtCompileTime) + : int(Flags)&RowMajorBit ? int(MatrixType::ColsAtCompileTime) + : int(MatrixType::RowsAtCompileTime) + }; }; -template class Map - : public MapBase, - typename MatrixType::template MakeBase< Map >::Type> +template class Map + : public MapBase, + typename MatrixType::template MakeBase< + Map + >::Type> { public: typedef MapBase::Type> Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Map) - inline int stride() const { return this->innerSize(); } + inline int innerStride() const + { + return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; + } - inline Map(const Scalar* data) : Base(data) {} + inline int outerStride() const + { + return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() + : IsVectorAtCompileTime ? this->size() + : int(Flags)&RowMajorBit ? this->cols() + : this->rows(); + } + + inline Map(const Scalar* data, const StrideType& stride = StrideType()) + : Base(data), m_stride(stride) {} - inline Map(const Scalar* data, int size) : Base(data, size) {} + inline Map(const Scalar* data, int size, const StrideType& stride = StrideType()) + : Base(data, size), m_stride(stride) {} - inline Map(const Scalar* data, int rows, int cols) : Base(data, rows, cols) {} + inline Map(const Scalar* data, int rows, int cols, const StrideType& stride = StrideType()) + : Base(data, rows, cols), m_stride(stride) {} +/* inline void resize(int rows, int cols) { EIGEN_ONLY_USED_FOR_DEBUG(rows); @@ -88,8 +115,12 @@ template class Map EIGEN_ONLY_USED_FOR_DEBUG(size); ei_assert(size == this->size()); } +*/ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map) + + protected: + StrideType m_stride; }; template diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index a922d8bb0..6bac2ed4c 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or @@ -37,12 +37,12 @@ template class MapBase { public: -// typedef MatrixBase Base; enum { IsRowMajor = (int(ei_traits::Flags) & RowMajorBit) ? 1 : 0, RowsAtCompileTime = ei_traits::RowsAtCompileTime, ColsAtCompileTime = ei_traits::ColsAtCompileTime, - SizeAtCompileTime = Base::SizeAtCompileTime + SizeAtCompileTime = Base::SizeAtCompileTime, + InnerStrideAtCompileTime = ei_traits::InnerStrideAtCompileTime }; typedef typename ei_traits::Scalar Scalar; @@ -52,90 +52,104 @@ template class MapBase inline int rows() const { return m_rows.value(); } inline int cols() const { return m_cols.value(); } - /** Returns the leading dimension (for matrices) or the increment (for vectors) to be used with data(). + /** \returns the pointer increment between two consecutive elements. * - * More precisely: - * - for a column major matrix it returns the number of elements between two successive columns - * - for a row major matrix it returns the number of elements between two successive rows - * - for a vector it returns the number of elements between two successive coefficients - * This function has to be used together with the MapBase::data() function. + * \note For vectors, the storage order is ignored. For matrices (non-vectors), we're looking + * at the increment between two consecutive elements within a slice in the inner direction. * - * \sa MapBase::data() */ - inline int stride() const { return derived().stride(); } + * \sa outerStride(), data(), rowStride(), colStride() + */ + inline int 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). + * + * \note For vectors, the storage order is ignored, there is only one inner slice, and so this method returns 1. + * For matrices (non-vectors), the notion of inner slice depends on the storage order. + * + * \sa innerStride(), data(), rowStride(), colStride() + */ + inline int outerStride() const { return derived().outerStride(); } + + /** \returns the pointer increment between two consecutive rows. + * + * \sa data(), innerStride(), outerStride(), colStride() + */ + inline int rowStride() const + { + return (RowsAtCompileTime==1 || IsRowMajor) ? outerStride() : innerStride(); + } + + /** \returns the pointer increment between two consecutive columns. + * + * \sa data(), innerStride(), outerStride(), rowStride() + */ + inline int colStride() const + { + return (RowsAtCompileTime==1 || IsRowMajor) ? innerStride() : outerStride(); + } /** Returns a pointer to the first coefficient of the matrix or vector. - * This function has to be used together with the stride() function. * - * \sa MapBase::stride() */ + * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride(). + * + * \sa innerStride(), outerStride() + */ inline const Scalar* data() const { return m_data; } inline const Scalar& coeff(int row, int col) const { - if(IsRowMajor) - return m_data[col + row * stride()]; - else // column-major - return m_data[row + col * stride()]; + return m_data[col * colStride() + row * rowStride()]; } inline Scalar& coeffRef(int row, int col) { - if(IsRowMajor) - return const_cast(m_data)[col + row * stride()]; - else // column-major - return const_cast(m_data)[row + col * stride()]; + return const_cast(m_data)[col * colStride() + row * rowStride()]; } inline const Scalar& coeff(int index) const { ei_assert(Derived::IsVectorAtCompileTime || (ei_traits::Flags & LinearAccessBit)); - if ( ((RowsAtCompileTime == 1) == IsRowMajor) || !int(Derived::IsVectorAtCompileTime) ) - return m_data[index]; - else - return m_data[index*stride()]; + return m_data[index * innerStride()]; } inline Scalar& coeffRef(int index) { ei_assert(Derived::IsVectorAtCompileTime || (ei_traits::Flags & LinearAccessBit)); - if ( ((RowsAtCompileTime == 1) == IsRowMajor) || !int(Derived::IsVectorAtCompileTime) ) - return const_cast(m_data)[index]; - else - return const_cast(m_data)[index*stride()]; + return const_cast(m_data)[index * innerStride()]; } template inline PacketScalar packet(int row, int col) const { return ei_ploadt - (m_data + (IsRowMajor ? col + row * stride() - : row + col * stride())); + (m_data + (col * colStride() + row * rowStride())); } template inline PacketScalar packet(int index) const { - return ei_ploadt(m_data + index); + return ei_ploadt(m_data + index * innerStride()); } template inline void writePacket(int row, int col, const PacketScalar& x) { ei_pstoret - (const_cast(m_data) + (IsRowMajor ? col + row * stride() - : row + col * stride()), x); + (const_cast(m_data) + (col * colStride() + row * rowStride()), x); } template inline void writePacket(int index, const PacketScalar& x) { ei_pstoret - (const_cast(m_data) + index, x); + (const_cast(m_data) + index * innerStride(), x); } inline MapBase(const Scalar* data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) - checkDataAlignment(); + checkSanity(); } inline MapBase(const Scalar* data, int size) @@ -146,7 +160,7 @@ template class MapBase EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) ei_assert(size >= 0); ei_assert(data == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == size); - checkDataAlignment(); + checkSanity(); } inline MapBase(const Scalar* data, int rows, int cols) @@ -155,7 +169,7 @@ template class MapBase ei_assert( (data == 0) || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); - checkDataAlignment(); + checkSanity(); } Derived& operator=(const MapBase& other) @@ -167,10 +181,12 @@ template class MapBase protected: - void checkDataAlignment() const + void checkSanity() const { ei_assert( ((!(ei_traits::Flags&AlignedBit)) || ((size_t(m_data)&0xf)==0)) && "data is not aligned"); + ei_assert( ((!(ei_traits::Flags&PacketAccessBit)) + || (innerStride()==1)) && "packet access incompatible with inner stride greater than 1"); } const Scalar* EIGEN_RESTRICT m_data; diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index 6f194ffba..e011ae8b9 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -120,7 +120,10 @@ struct ei_traits > MaxRowsAtCompileTime = _MaxRows, MaxColsAtCompileTime = _MaxCols, Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret, - CoeffReadCost = NumTraits::ReadCost + CoeffReadCost = NumTraits::ReadCost, + InnerStrideAtCompileTime = 1, + OuterStrideAtCompileTime = (RowsAtCompileTime==1||ColsAtCompileTime==1) ? 1 + : (int(Flags)&RowMajorBit) ? RowsAtCompileTime : ColsAtCompileTime }; }; @@ -318,6 +321,9 @@ class Matrix void swap(MatrixBase EIGEN_REF_TO_TEMPORARY other) { this->_swap(other.derived()); } + inline int innerStride() const { return 1; } + inline int outerStride() const { return this->innerSize(); } + /////////// Geometry module /////////// template diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h index af05773ee..53277169c 100644 --- a/Eigen/src/Core/Product.h +++ b/Eigen/src/Core/Product.h @@ -336,7 +336,7 @@ template<> struct ei_gemv_selector ei_cache_friendly_product_colmajor_times_vector ( dest.size(), - &actualLhs.const_cast_derived().coeffRef(0,0), actualLhs.stride(), + &actualLhs.const_cast_derived().coeffRef(0,0), ei_outer_stride_or_outer_size(actualLhs), actualRhs, actualDest, actualAlpha); if (!EvalToDest) @@ -381,7 +381,7 @@ template<> struct ei_gemv_selector ei_cache_friendly_product_rowmajor_times_vector ( - &actualLhs.const_cast_derived().coeffRef(0,0), actualLhs.stride(), + &actualLhs.const_cast_derived().coeffRef(0,0), ei_outer_stride_or_outer_size(actualLhs), rhs_data, prod.rhs().size(), dest, actualAlpha); if (!DirectlyUseRhs) ei_aligned_stack_delete(Scalar, rhs_data, prod.rhs().size()); diff --git a/Eigen/src/Core/ReturnByValue.h b/Eigen/src/Core/ReturnByValue.h index 920269365..8d45fc31b 100644 --- a/Eigen/src/Core/ReturnByValue.h +++ b/Eigen/src/Core/ReturnByValue.h @@ -34,14 +34,9 @@ struct ei_traits > : public ei_traits::ReturnMatrixType> { enum { - // FIXME had to remove the DirectAccessBit for usage like - // matrix.inverse().block(...) - // because the Block ctor with direct access - // wants to call coeffRef() to get an address, and that fails (infinite recursion) as ReturnByValue - // doesnt implement coeffRef(). - // The fact that I had to do that shows that when doing xpr.block() with a non-direct-access xpr, - // even if xpr has the EvalBeforeNestingBit, the block() doesn't use direct access on the evaluated - // xpr. + // We're disabling the DirectAccess because e.g. the constructor of + // the Block-with-DirectAccess expression requires to have a coeffRef method. + // Also, we don't want to have to implement the stride stuff. Flags = (ei_traits::ReturnMatrixType>::Flags | EvalBeforeNestingBit) & ~DirectAccessBit }; diff --git a/Eigen/src/Core/Transpose.h b/Eigen/src/Core/Transpose.h index bd06d8464..753a67ee0 100644 --- a/Eigen/src/Core/Transpose.h +++ b/Eigen/src/Core/Transpose.h @@ -80,6 +80,9 @@ template class Transpose typename ei_cleantype::type& nestedExpression() { return m_matrix.const_cast_derived(); } + enum { InnerStrideAtCompileTime = ei_inner_stride_at_compile_time::ret, + OuterStrideAtCompileTime = ei_outer_stride_at_compile_time::ret }; + protected: const typename MatrixType::Nested m_matrix; }; @@ -93,7 +96,8 @@ template class TransposeImpl typedef typename MatrixType::template MakeBase >::Type Base; EIGEN_DENSE_PUBLIC_INTERFACE(Transpose) - inline int stride() const { return derived().nestedExpression().stride(); } + inline int innerStride() const { return derived().nestedExpression().innerStride(); } + inline int outerStride() const { return derived().nestedExpression().outerStride(); } inline Scalar* data() { return derived().nestedExpression().data(); } inline const Scalar* data() const { return derived().nestedExpression().data(); } diff --git a/Eigen/src/Core/products/GeneralMatrixMatrix.h b/Eigen/src/Core/products/GeneralMatrixMatrix.h index beec17ee4..03c77cc78 100644 --- a/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -147,6 +147,7 @@ class GeneralProduct const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); + ei_assert(ei_inner_stride_at_compile_time::ret == 1); Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) * RhsBlasTraits::extractScalarFactor(m_rhs); @@ -158,9 +159,9 @@ class GeneralProduct (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor> ::run( this->rows(), this->cols(), lhs.cols(), - (const Scalar*)&(lhs.const_cast_derived().coeffRef(0,0)), lhs.stride(), - (const Scalar*)&(rhs.const_cast_derived().coeffRef(0,0)), rhs.stride(), - (Scalar*)&(dst.coeffRef(0,0)), dst.stride(), + (const Scalar*)&(lhs.const_cast_derived().coeffRef(0,0)), ei_outer_stride_or_outer_size(lhs), + (const Scalar*)&(rhs.const_cast_derived().coeffRef(0,0)), ei_outer_stride_or_outer_size(rhs), + (Scalar*)&(dst.coeffRef(0,0)), ei_outer_stride_or_outer_size(dst), actualAlpha); } }; diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index aed0abe6d..c2d45dc30 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -1,7 +1,8 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2007-2009 Benoit Jacob +// Copyright (C) 2007-2010 Benoit Jacob +// Copyright (C) 2008-2009 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -60,7 +61,9 @@ template class DiagonalProduct; template class Diagonal; -template class Map; +template class Stride; +template > class Map; + template class TriangularBase; template class TriangularView; template class SelfAdjointView; diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 619e7664d..5252b28c5 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -2,7 +2,7 @@ // for linear algebra. // // Copyright (C) 2008 Gael Guennebaud -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008 Benoit Jacob // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -46,7 +46,7 @@ // if native static_assert is enabled, let's use it #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG); - #else // CXX0X + #else // not CXX0X template struct ei_static_assert {}; @@ -81,7 +81,8 @@ BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX, THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES, + YOU_ALREADY_SPECIFIED_THIS_STRIDE }; }; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index a86e7be89..8ddf4450a 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -50,7 +50,7 @@ template class ei_int_if_dynamic { public: EIGEN_EMPTY_STRUCT_CTOR(ei_int_if_dynamic) - explicit ei_int_if_dynamic(int) {} + explicit ei_int_if_dynamic(int v) { EIGEN_ONLY_USED_FOR_DEBUG(v); ei_assert(v == Value); } static int value() { return Value; } void setValue(int) {} }; @@ -58,7 +58,7 @@ template class ei_int_if_dynamic template<> class ei_int_if_dynamic { int m_value; - ei_int_if_dynamic() {} + ei_int_if_dynamic() { ei_assert(false); } public: explicit ei_int_if_dynamic(int value) : m_value(value) {} int value() const { return m_value; } -- cgit v1.2.3