* remove EnforceAlignedAccess option to Block, VectorBlock, Map and MapBase

because thanks to the previous commit this is not needed anymore
* add a more general ForceAlignedAccess expression which can be used for any expression.
  It is already used by StableNorm.h.
This commit is contained in:
Gael Guennebaud 2009-11-20 16:30:14 +01:00
parent eb8f450071
commit 4af1753b6f
10 changed files with 182 additions and 96 deletions

View File

@ -164,6 +164,7 @@ struct Dense {};
#include "src/Core/util/BlasUtil.h"
#include "src/Core/MatrixStorage.h"
#include "src/Core/NestByValue.h"
#include "src/Core/ForceAlignedAccess.h"
#include "src/Core/ReturnByValue.h"
#include "src/Core/NoAlias.h"
#include "src/Core/Matrix.h"

View File

@ -33,10 +33,6 @@
* \param MatrixType the type of the object in which we are taking a block
* \param BlockRows the number of rows of the block we are taking at compile time (optional)
* \param BlockCols the number of columns of the block we are taking at compile time (optional)
* \param _PacketAccess \internal used to enforce aligned loads in expressions such as
* \code mat.block() += other; \endcode. Possible values are
* \c AsRequested (default) and \c EnforceAlignedAccess.
* See class MapBase for more details.
* \param _DirectAccessStatus \internal used for partial specialization
*
* This class represents an expression of either a fixed-size or dynamic-size block. It is the return
@ -61,8 +57,8 @@
*
* \sa MatrixBase::block(int,int,int,int), MatrixBase::block(int,int), class VectorBlock
*/
template<typename MatrixType, int BlockRows, int BlockCols, int _PacketAccess, int _DirectAccessStatus>
struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectAccessStatus> >
template<typename MatrixType, int BlockRows, int BlockCols, int _DirectAccessStatus>
struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _DirectAccessStatus> >
{
typedef typename ei_traits<MatrixType>::Scalar Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
@ -82,16 +78,12 @@ struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectA
? PacketAccessBit : 0,
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
Flags = (ei_traits<MatrixType>::Flags & (HereditaryBits | MaskPacketAccessBit | DirectAccessBit)) | FlagsLinearAccessBit,
CoeffReadCost = ei_traits<MatrixType>::CoeffReadCost,
PacketAccess = _PacketAccess
CoeffReadCost = ei_traits<MatrixType>::CoeffReadCost
};
typedef typename ei_meta_if<int(PacketAccess)==EnforceAlignedAccess,
Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectAccessStatus>&,
Block<MatrixType, BlockRows, BlockCols, EnforceAlignedAccess, _DirectAccessStatus> >::ret AlignedDerivedType;
};
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, int _DirectAccessStatus> class Block
: public MatrixBase<Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus> >
template<typename MatrixType, int BlockRows, int BlockCols, int _DirectAccessStatus> class Block
: public MatrixBase<Block<MatrixType, BlockRows, BlockCols, _DirectAccessStatus> >
{
public:
@ -219,26 +211,16 @@ template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, in
};
/** \internal */
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
class Block<MatrixType,BlockRows,BlockCols,PacketAccess,HasDirectAccess>
: public MapBase<Block<MatrixType, BlockRows, BlockCols,PacketAccess,HasDirectAccess> >
template<typename MatrixType, int BlockRows, int BlockCols>
class Block<MatrixType,BlockRows,BlockCols,HasDirectAccess>
: public MapBase<Block<MatrixType, BlockRows, BlockCols,HasDirectAccess> >
{
public:
_EIGEN_GENERIC_PUBLIC_INTERFACE(Block, MapBase<Block>)
class InnerIterator;
typedef typename ei_traits<Block>::AlignedDerivedType AlignedDerivedType;
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==EnforceAlignedAccess?AsRequested:EnforceAlignedAccess,HasDirectAccess>;
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
AlignedDerivedType _convertToEnforceAlignedAccess()
{
return Block<MatrixType,BlockRows,BlockCols,EnforceAlignedAccess,HasDirectAccess>
(m_matrix, Base::m_data, Base::m_rows.value(), Base::m_cols.value());
}
/** Column or Row constructor
*/
inline Block(const MatrixType& matrix, int i)

View File

@ -0,0 +1,151 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_FORCEALIGNEDACCESS_H
#define EIGEN_FORCEALIGNEDACCESS_H
/** \class ForceAlignedAccess
*
* \brief Enforce aligned packet loads and stores regardless of what is requested
*
* \param ExpressionType the type of the object of which we are forcing aligned packet access
*
* This class is the return type of MatrixBase::forceAlignedAccess()
* and most of the time this is the only way it is used.
*
* \sa MatrixBase::forceAlignedAccess()
*/
template<typename ExpressionType>
struct ei_traits<ForceAlignedAccess<ExpressionType> > : public ei_traits<ExpressionType>
{};
template<typename ExpressionType> class ForceAlignedAccess
: public MatrixBase<ForceAlignedAccess<ExpressionType> >
{
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(ForceAlignedAccess)
inline ForceAlignedAccess(const ExpressionType& matrix) : m_expression(matrix) {}
inline int rows() const { return m_expression.rows(); }
inline int cols() const { return m_expression.cols(); }
inline int stride() const { return m_expression.stride(); }
inline const CoeffReturnType coeff(int row, int col) const
{
return m_expression.coeff(row, col);
}
inline Scalar& coeffRef(int row, int col)
{
return m_expression.const_cast_derived().coeffRef(row, col);
}
inline const CoeffReturnType coeff(int index) const
{
return m_expression.coeff(index);
}
inline Scalar& coeffRef(int index)
{
return m_expression.const_cast_derived().coeffRef(index);
}
template<int LoadMode>
inline const PacketScalar packet(int row, int col) const
{
return m_expression.template packet<Aligned>(row, col);
}
template<int LoadMode>
inline void writePacket(int row, int col, const PacketScalar& x)
{
m_expression.const_cast_derived().template writePacket<Aligned>(row, col, x);
}
template<int LoadMode>
inline const PacketScalar packet(int index) const
{
return m_expression.template packet<Aligned>(index);
}
template<int LoadMode>
inline void writePacket(int index, const PacketScalar& x)
{
m_expression.const_cast_derived().template writePacket<Aligned>(index, x);
}
operator const ExpressionType&() const { return m_expression; }
protected:
const ExpressionType& m_expression;
private:
ForceAlignedAccess& operator=(const ForceAlignedAccess&);
};
/** \returns an expression of *this with forced aligned access
* \sa forceAlignedAccessIf(),class ForceAlignedAccess
*/
template<typename Derived>
inline const ForceAlignedAccess<Derived>
MatrixBase<Derived>::forceAlignedAccess() const
{
return ForceAlignedAccess<Derived>(derived());
}
/** \returns an expression of *this with forced aligned access
* \sa forceAlignedAccessIf(), class ForceAlignedAccess
*/
template<typename Derived>
inline ForceAlignedAccess<Derived>
MatrixBase<Derived>::forceAlignedAccess()
{
return ForceAlignedAccess<Derived>(derived());
}
/** \returns an expression of *this with forced aligned access if \a Enable is true.
* \sa forceAlignedAccess(), class ForceAlignedAccess
*/
template<typename Derived>
template<bool Enable>
inline const typename ei_meta_if<Enable,ForceAlignedAccess<Derived>,Derived&>::ret
MatrixBase<Derived>::forceAlignedAccessIf() const
{
return derived();
}
/** \returns an expression of *this with forced aligned access if \a Enable is true.
* \sa forceAlignedAccess(), class ForceAlignedAccess
*/
template<typename Derived>
template<bool Enable>
inline typename ei_meta_if<Enable,ForceAlignedAccess<Derived>,Derived&>::ret
MatrixBase<Derived>::forceAlignedAccessIf()
{
return derived();
}
#endif // EIGEN_FORCEALIGNEDACCESS_H

View File

@ -31,8 +31,8 @@
* \brief A matrix or vector expression mapping an existing array of data.
*
* \param MatrixType the equivalent matrix type of the mapped data
* \param PointerAlignment specifies whether the pointer is \c Aligned, or \c Unaligned.
* The default is \c Unaligned.
* \param Options specifies whether the pointer is \c Aligned, or \c Unaligned.
* The default is \c Unaligned.
*
* This class represents a matrix or vector expression mapping an existing array of data.
* It can be used to let Eigen interface without any overhead with non-Eigen data structures,
@ -46,23 +46,15 @@
*
* This class is the return type of Matrix::Map() but can also be used directly.
*
* \b Note \b to \b Eigen \b developers: The template parameter \c PointerAlignment
* can also be or-ed with \c EnforceAlignedAccess in order to enforce aligned read
* in expressions such as \code A += B; \endcode. See class MapBase for further details.
*
* \sa Matrix::Map()
*/
template<typename MatrixType, int Options>
struct ei_traits<Map<MatrixType, Options> > : public ei_traits<MatrixType>
{
enum {
PacketAccess = Options & EnforceAlignedAccess,
Flags = (Options&Aligned)==Aligned ? ei_traits<MatrixType>::Flags | AlignedBit
: ei_traits<MatrixType>::Flags & ~AlignedBit
};
typedef typename ei_meta_if<int(PacketAccess)==EnforceAlignedAccess,
Map<MatrixType, Options>&,
Map<MatrixType, Options|EnforceAlignedAccess> >::ret AlignedDerivedType;
};
template<typename MatrixType, int Options> class Map
@ -71,15 +63,9 @@ template<typename MatrixType, int Options> class Map
public:
_EIGEN_GENERIC_PUBLIC_INTERFACE(Map, MapBase<Map>)
typedef typename ei_traits<Map>::AlignedDerivedType AlignedDerivedType;
inline int stride() const { return this->innerSize(); }
AlignedDerivedType _convertToEnforceAlignedAccess()
{
return AlignedDerivedType(Base::m_data, Base::m_rows.value(), Base::m_cols.value());
}
inline Map(const Scalar* data) : Base(data) {}
inline Map(const Scalar* data, int size) : Base(data, size) {}

View File

@ -30,20 +30,6 @@
*
* \brief Base class for Map and Block expression with direct access
*
* Expression classes inheriting MapBase must define the constant \c PacketAccess,
* and type \c AlignedDerivedType in their respective ei_traits<> specialization structure.
* The value of \c PacketAccess can be either \b AsRequested, or set to \b EnforceAlignedAccess which
* enforces both aligned loads and stores.
*
* \c EnforceAlignedAccess is automatically set in expressions such as
* \code A += B; \endcode where A is either a Block or a Map. Here,
* this expression is transfomed into \code A = A_with_EnforceAlignedAccess + B; \endcode
* avoiding unaligned loads from A. Indeed, since Eigen's packet evaluation mechanism
* automatically align to the destination matrix, we know that loads to A will be aligned too.
*
* The type \c AlignedDerivedType should correspond to the equivalent expression type
* with \c PacketAccess set to \c EnforceAlignedAccess.
*
* \sa class Map, class Block
*/
template<typename Derived> class MapBase
@ -54,13 +40,11 @@ template<typename Derived> class MapBase
typedef MatrixBase<Derived> Base;
enum {
IsRowMajor = (int(ei_traits<Derived>::Flags) & RowMajorBit) ? 1 : 0,
PacketAccess = ei_traits<Derived>::PacketAccess,
RowsAtCompileTime = ei_traits<Derived>::RowsAtCompileTime,
ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
SizeAtCompileTime = Base::SizeAtCompileTime
};
typedef typename ei_traits<Derived>::AlignedDerivedType AlignedDerivedType;
typedef typename ei_traits<Derived>::Scalar Scalar;
typedef typename Base::PacketScalar PacketScalar;
using Base::derived;
@ -85,21 +69,6 @@ template<typename Derived> class MapBase
* \sa MapBase::stride() */
inline const Scalar* data() const { return m_data; }
template<bool IsEnforceAlignedAccess,typename Dummy> struct force_aligned_impl {
static AlignedDerivedType run(MapBase& a) { return a.derived(); }
};
template<typename Dummy> struct force_aligned_impl<false,Dummy> {
static AlignedDerivedType run(MapBase& a) { return a.derived()._convertToEnforceAlignedAccess(); }
};
/** \returns an expression equivalent to \c *this but having the \c PacketAccess constant
* set to \c EnforceAlignedAccess. Must be reimplemented by the derived class. */
AlignedDerivedType forceAligned()
{
return force_aligned_impl<int(PacketAccess)==int(EnforceAlignedAccess),Derived>::run(*this);
}
inline const Scalar& coeff(int row, int col) const
{
if(IsRowMajor)
@ -137,7 +106,7 @@ template<typename Derived> class MapBase
template<int LoadMode>
inline PacketScalar packet(int row, int col) const
{
return ei_ploadt<Scalar, int(PacketAccess) == EnforceAlignedAccess ? Aligned : LoadMode>
return ei_ploadt<Scalar, LoadMode>
(m_data + (IsRowMajor ? col + row * stride()
: row + col * stride()));
}
@ -145,13 +114,13 @@ template<typename Derived> class MapBase
template<int LoadMode>
inline PacketScalar packet(int index) const
{
return ei_ploadt<Scalar, int(PacketAccess) == EnforceAlignedAccess ? Aligned : LoadMode>(m_data + index);
return ei_ploadt<Scalar, LoadMode>(m_data + index);
}
template<int StoreMode>
inline void writePacket(int row, int col, const PacketScalar& x)
{
ei_pstoret<Scalar, PacketScalar, int(PacketAccess) == EnforceAlignedAccess ? Aligned : StoreMode>
ei_pstoret<Scalar, PacketScalar, StoreMode>
(const_cast<Scalar*>(m_data) + (IsRowMajor ? col + row * stride()
: row + col * stride()), x);
}
@ -159,7 +128,7 @@ template<typename Derived> class MapBase
template<int StoreMode>
inline void writePacket(int index, const PacketScalar& x)
{
ei_pstoret<Scalar, PacketScalar, int(PacketAccess) == EnforceAlignedAccess ? Aligned : StoreMode>
ei_pstoret<Scalar, PacketScalar, StoreMode>
(const_cast<Scalar*>(m_data) + index, x);
}

View File

@ -548,6 +548,10 @@ template<typename Derived> class MatrixBase
inline int stride(void) const { return derived().stride(); }
inline const NestByValue<Derived> nestByValue() const;
inline const ForceAlignedAccess<Derived> forceAlignedAccess() const;
inline ForceAlignedAccess<Derived> forceAlignedAccess();
template<bool Enable> inline const typename ei_meta_if<Enable,ForceAlignedAccess<Derived>,Derived&>::ret forceAlignedAccessIf() const;
template<bool Enable> inline typename ei_meta_if<Enable,ForceAlignedAccess<Derived>,Derived&>::ret forceAlignedAccessIf();
Scalar sum() const;
Scalar mean() const;

View File

@ -59,7 +59,7 @@ MatrixBase<Derived>::stableNorm() const
RealScalar invScale = 1;
RealScalar ssq = 0; // sum of square
enum {
Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? EnforceAlignedAccess : AsRequested
Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
};
int n = size();
int bi=0;
@ -70,7 +70,7 @@ MatrixBase<Derived>::stableNorm() const
ei_stable_norm_kernel(start(bi), ssq, scale, invScale);
}
for (; bi<n; bi+=blockSize)
ei_stable_norm_kernel(VectorBlock<Derived,Dynamic,Alignment>(derived(),bi,std::min(blockSize, n - bi)), ssq, scale, invScale);
ei_stable_norm_kernel(segment(bi,std::min(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
return scale * ei_sqrt(ssq);
}

View File

@ -32,10 +32,6 @@
*
* \param VectorType the type of the object in which we are taking a sub-vector
* \param Size size of the sub-vector we are taking at compile time (optional)
* \param _PacketAccess allows to enforce aligned loads and stores if set to ForceAligned.
* The default is AsRequested. This parameter is internaly used by Eigen
* in expressions such as \code mat.segment() += other; \endcode and most of
* the time this is the only way it is used.
*
* This class represents an expression of either a fixed-size or dynamic-size sub-vector.
* It is the return type of MatrixBase::segment(int,int) and MatrixBase::segment<int>(int) and
@ -59,25 +55,22 @@
*
* \sa class Block, MatrixBase::segment(int,int,int,int), MatrixBase::segment(int,int)
*/
template<typename VectorType, int Size, int _PacketAccess>
struct ei_traits<VectorBlock<VectorType, Size, _PacketAccess> >
template<typename VectorType, int Size>
struct ei_traits<VectorBlock<VectorType, Size> >
: public ei_traits<Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size,
_PacketAccess> >
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size> >
{
};
template<typename VectorType, int Size, int PacketAccess> class VectorBlock
template<typename VectorType, int Size> class VectorBlock
: public Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size,
PacketAccess>
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size>
{
typedef Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size,
PacketAccess> _Base;
ei_traits<VectorType>::ColsAtCompileTime==1 ? 1 : Size> _Base;
enum {
IsColVector = ei_traits<VectorType>::ColsAtCompileTime==1
};

View File

@ -189,7 +189,6 @@ const unsigned int UnitUpperTriangular = UpperTriangularBit | UnitDiagBit;
const unsigned int UnitLowerTriangular = LowerTriangularBit | UnitDiagBit;
enum { Unaligned=0, Aligned=1 };
enum { AsRequested=0, EnforceAlignedAccess=2 };
enum { ConditionalJumpCost = 5 };
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
enum DirectionType { Vertical, Horizontal, BothDirections };

View File

@ -37,11 +37,12 @@ template<typename _Scalar, int _Rows, int _Cols,
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged;
template<typename ExpressionType, template <typename> class StorageBase > class NoAlias;
template<typename ExpressionType> class NestByValue;
template<typename ExpressionType> class ForceAlignedAccess;
template<typename ExpressionType> class SwapWrapper;
template<typename MatrixType> class Minor;
template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic, int PacketAccess=AsRequested,
template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic,
int _DirectAccessStatus = (ei_traits<MatrixType>::Flags&DirectAccessBit) ? HasDirectAccess : NoDirectAccess> class Block;
template<typename MatrixType, int Size=Dynamic, int PacketAccess=AsRequested> class VectorBlock;
template<typename MatrixType, int Size=Dynamic> class VectorBlock;
template<typename MatrixType> class Transpose;
template<typename MatrixType> class Conjugate;
template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp;
@ -57,7 +58,7 @@ template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime=SizeA
template<typename MatrixType, typename DiagonalType, int ProductOrder> class DiagonalProduct;
template<typename MatrixType, int Index> class Diagonal;
template<typename MatrixType, int PacketAccess = AsRequested> class Map;
template<typename MatrixType, int Options=Unaligned> class Map;
template<typename Derived> class TriangularBase;
template<typename MatrixType, unsigned int Mode> class TriangularView;
template<typename MatrixType, unsigned int Mode> class SelfAdjointView;