merge and add start/end to Eigen2Support

This commit is contained in:
Gael Guennebaud
2010-01-05 13:07:32 +01:00
78 changed files with 1072 additions and 592 deletions

View File

@@ -49,6 +49,7 @@ private:
InnerMaxSize = int(Derived::Flags)&RowMajorBit
? Derived::MaxColsAtCompileTime
: Derived::MaxRowsAtCompileTime,
MaxSizeAtCompileTime = ei_size_at_compile_time<Derived::MaxColsAtCompileTime,Derived::MaxRowsAtCompileTime>::ret,
PacketSize = ei_packet_traits<typename Derived::Scalar>::size
};
@@ -60,9 +61,9 @@ private:
&& int(DstIsAligned) && int(SrcIsAligned),
MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
MayLinearVectorize = MightVectorize && MayLinearize
&& (DstIsAligned || InnerMaxSize == Dynamic),
&& (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. See remark below about InnerMaxSize. */
so it's only good for large enough sizes. */
MaySliceVectorize = MightVectorize && 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
@@ -385,7 +386,7 @@ struct ei_assign_impl<Derived1, Derived2, LinearVectorizedTraversal, NoUnrolling
const int size = dst.size();
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
const int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
: ei_alignmentOffset(&dst.coeffRef(0), size);
: ei_first_aligned(&dst.coeffRef(0), size);
const int alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
for(int index = 0; index < alignedStart; ++index)
@@ -430,7 +431,7 @@ struct ei_assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling>
const int outerSize = dst.outerSize();
const int alignedStep = (packetSize - dst.stride() % packetSize) & packetAlignedMask;
int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
: ei_alignmentOffset(&dst.coeffRef(0,0), innerSize);
: ei_first_aligned(&dst.coeffRef(0,0), innerSize);
for(int i = 0; i < outerSize; ++i)
{
@@ -480,11 +481,11 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
ei_assert(rows() == other.rows() && cols() == other.cols());
ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
#ifdef EIGEN_DEBUG_ASSIGN
ei_assign_traits<Derived, OtherDerived>::debug();
#endif
ei_assert(rows() == other.rows() && cols() == other.cols());
ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
#ifndef EIGEN_NO_DEBUG
checkTransposeAliasing(other.derived());
#endif

View File

@@ -379,36 +379,33 @@ EIGEN_STRONG_INLINE void DenseBase<Derived>::copyPacket(int index, const DenseBa
other.derived().template packet<LoadMode>(index));
}
template<typename Derived, typename Integer, bool JustReturnZero>
struct ei_alignmentOffset_impl
template<typename Derived, bool JustReturnZero>
struct ei_first_aligned_impl
{
inline static Integer run(const DenseBase<Derived>&, Integer)
inline static int run(const DenseBase<Derived>&)
{ return 0; }
};
template<typename Derived, typename Integer>
struct ei_alignmentOffset_impl<Derived, Integer, false>
template<typename Derived>
struct ei_first_aligned_impl<Derived, false>
{
inline static Integer run(const DenseBase<Derived>& m, Integer maxOffset)
inline static int run(const DenseBase<Derived>& m)
{
return ei_alignmentOffset(&m.const_cast_derived().coeffRef(0,0), maxOffset);
return ei_first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size());
}
};
/** \internal \returns the number of elements which have to be skipped, starting
* from the address of coeffRef(0,0), to find the first 16-byte aligned element.
/** \internal \returns the index of the first element of the array that is well aligned for vectorization.
*
* \note If the expression doesn't have the DirectAccessBit, this function returns 0.
*
* There is also the variant ei_alignmentOffset(const Scalar*, Integer) defined in Memory.h.
* There is also the variant ei_first_aligned(const Scalar*, Integer) defined in Memory.h. See it for more
* documentation.
*/
template<typename Derived, typename Integer>
inline static Integer ei_alignmentOffset(const DenseBase<Derived>& m, Integer maxOffset)
template<typename Derived>
inline static int ei_first_aligned(const DenseBase<Derived>& m)
{
return ei_alignmentOffset_impl<Derived, Integer,
(Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)>
::run(m, maxOffset);
return ei_first_aligned_impl
<Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)>
::run(m);
}
#endif

View File

@@ -290,11 +290,11 @@ template<typename Derived> class DenseBase
VectorBlock<Derived> segment(int start, int size);
const VectorBlock<Derived> segment(int start, int size) const;
VectorBlock<Derived> start(int size);
const VectorBlock<Derived> start(int size) const;
VectorBlock<Derived> head(int size);
const VectorBlock<Derived> head(int size) const;
VectorBlock<Derived> end(int size);
const VectorBlock<Derived> end(int size) const;
VectorBlock<Derived> tail(int size);
const VectorBlock<Derived> tail(int size) const;
typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols);
const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const;
@@ -309,11 +309,11 @@ template<typename Derived> class DenseBase
template<int CRows, int CCols>
const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const;
template<int Size> VectorBlock<Derived,Size> start(void);
template<int Size> const VectorBlock<Derived,Size> start() const;
template<int Size> VectorBlock<Derived,Size> head(void);
template<int Size> const VectorBlock<Derived,Size> head() const;
template<int Size> VectorBlock<Derived,Size> end();
template<int Size> const VectorBlock<Derived,Size> end() const;
template<int Size> VectorBlock<Derived,Size> tail();
template<int Size> const VectorBlock<Derived,Size> tail() const;
template<int Size> VectorBlock<Derived,Size> segment(int start);
template<int Size> const VectorBlock<Derived,Size> segment(int start) const;

View File

@@ -218,7 +218,7 @@ inline float ei_norm1(const std::complex<float> &x) { return(ei_abs(x.real()) +
inline std::complex<float> ei_exp(std::complex<float> x) { return std::exp(x); }
inline std::complex<float> ei_sin(std::complex<float> x) { return std::sin(x); }
inline std::complex<float> ei_cos(std::complex<float> x) { return std::cos(x); }
inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0; }
inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0.f; }
template<> inline std::complex<float> ei_random()
{
@@ -255,7 +255,7 @@ inline double ei_norm1(const std::complex<double> &x) { return(ei_abs(x.real())
inline std::complex<double> ei_exp(std::complex<double> x) { return std::exp(x); }
inline std::complex<double> ei_sin(std::complex<double> x) { return std::sin(x); }
inline std::complex<double> ei_cos(std::complex<double> x) { return std::cos(x); }
inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0; }
inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0.; }
template<> inline std::complex<double> ei_random()
{

View File

@@ -397,6 +397,15 @@ template<typename Derived> class MatrixBase
inline const Cwise<Derived> cwise() const;
inline Cwise<Derived> cwise();
VectorBlock<Derived> start(int size);
const VectorBlock<Derived> start(int size) const;
VectorBlock<Derived> end(int size);
const VectorBlock<Derived> end(int size) const;
template<int Size> VectorBlock<Derived,Size> start();
template<int Size> const VectorBlock<Derived,Size> start() const;
template<int Size> VectorBlock<Derived,Size> end();
template<int Size> const VectorBlock<Derived,Size> end() const;
template<typename OtherDerived>
typename ei_plain_matrix_type_column_major<OtherDerived>::type
solveTriangular(const MatrixBase<OtherDerived>& other) const;

View File

@@ -98,7 +98,7 @@ template<typename T, int _Rows, int _Cols, int _Options> class ei_matrix_storage
inline explicit ei_matrix_storage() {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) {}
inline ei_matrix_storage(int,int,int) {}
inline void swap(ei_matrix_storage& other) {}
inline void swap(ei_matrix_storage& ) {}
inline static int rows(void) {return _Rows;}
inline static int cols(void) {return _Cols;}
inline void resize(int,int,int) {}

View File

@@ -209,7 +209,7 @@ struct ei_redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
{
const int size = mat.size();
const int packetSize = ei_packet_traits<Scalar>::size;
const int alignedStart = ei_alignmentOffset(mat,size);
const int alignedStart = ei_first_aligned(mat);
enum {
alignment = (Derived::Flags & DirectAccessBit) || (Derived::Flags & AlignedBit)
? Aligned : Unaligned

View File

@@ -25,13 +25,27 @@
#ifndef EIGEN_SOLVETRIANGULAR_H
#define EIGEN_SOLVETRIANGULAR_H
template<typename Lhs, typename Rhs, int Side>
class ei_trsolve_traits
{
private:
enum {
RhsIsVectorAtCompileTime = (Side==OnTheLeft ? Rhs::ColsAtCompileTime : Rhs::RowsAtCompileTime)==1
};
public:
enum {
Unrolling = (RhsIsVectorAtCompileTime && Rhs::SizeAtCompileTime <= 8)
? CompleteUnrolling : NoUnrolling,
RhsVectors = RhsIsVectorAtCompileTime ? 1 : Dynamic
};
};
template<typename Lhs, typename Rhs,
int Mode, // can be Upper/Lower | UnitDiag
int Side, // can be OnTheLeft/OnTheRight
int Unrolling = Rhs::IsVectorAtCompileTime && Rhs::SizeAtCompileTime <= 8 // FIXME
? CompleteUnrolling : NoUnrolling,
int Mode, // can be Upper/Lower | UnitDiag
int Unrolling = ei_trsolve_traits<Lhs,Rhs,Side>::Unrolling,
int StorageOrder = (int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor,
int RhsCols = Rhs::ColsAtCompileTime
int RhsVectors = ei_trsolve_traits<Lhs,Rhs,Side>::RhsVectors
>
struct ei_triangular_solver_selector;
@@ -142,12 +156,24 @@ struct ei_triangular_solver_selector<Lhs,Rhs,OnTheLeft,Mode,NoUnrolling,ColMajor
}
};
// transpose OnTheRight cases for vectors
template<typename Lhs, typename Rhs, int Mode, int Unrolling, int StorageOrder>
struct ei_triangular_solver_selector<Lhs,Rhs,OnTheRight,Mode,Unrolling,StorageOrder,1>
{
static void run(const Lhs& lhs, Rhs& rhs)
{
Transpose<Rhs> rhsTr(rhs);
Transpose<Lhs> lhsTr(lhs);
ei_triangular_solver_selector<Transpose<Lhs>,Transpose<Rhs>,OnTheLeft,TriangularView<Lhs,Mode>::TransposeMode>::run(lhsTr,rhsTr);
}
};
template <typename Scalar, int Side, int Mode, bool Conjugate, int TriStorageOrder, int OtherStorageOrder>
struct ei_triangular_solve_matrix;
// the rhs is a matrix
template<typename Lhs, typename Rhs, int Side, int Mode, int StorageOrder, int RhsCols>
struct ei_triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,StorageOrder,RhsCols>
template<typename Lhs, typename Rhs, int Side, int Mode, int StorageOrder>
struct ei_triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,StorageOrder,Dynamic>
{
typedef typename Rhs::Scalar Scalar;
typedef ei_blas_traits<Lhs> LhsProductTraits;

View File

@@ -65,9 +65,9 @@ MatrixBase<Derived>::stableNorm() const
int bi=0;
if ((int(Flags)&DirectAccessBit) && !(int(Flags)&AlignedBit))
{
bi = ei_alignmentOffset(&const_cast_derived().coeffRef(0), n);
bi = ei_first_aligned(&const_cast_derived().coeffRef(0), n);
if (bi>0)
ei_stable_norm_kernel(this->start(bi), ssq, scale, invScale);
ei_stable_norm_kernel(this->head(bi), ssq, scale, invScale);
}
for (; bi<n; bi+=blockSize)
ei_stable_norm_kernel(this->segment(bi,std::min(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);

View File

@@ -95,12 +95,14 @@ template<typename Derived> class TriangularBase : public AnyMatrixBase<Derived>
|| ((Mode==StrictlyLowerTriangular || Mode==UnitLowerTriangular) && col<row));
}
#ifdef EIGEN_INTERNAL_DEBUGGING
void check_coordinates_internal(int row, int col)
{
#ifdef EIGEN_INTERNAL_DEBUGGING
check_coordinates(row, col);
#endif
}
#else
void check_coordinates_internal(int , int ) {}
#endif
};

View File

@@ -154,16 +154,16 @@ DenseBase<Derived>::segment(int start, int size) const
*/
template<typename Derived>
inline VectorBlock<Derived>
DenseBase<Derived>::start(int size)
DenseBase<Derived>::head(int size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived>(derived(), 0, size);
}
/** This is the const version of start(int).*/
/** This is the const version of head(int).*/
template<typename Derived>
inline const VectorBlock<Derived>
DenseBase<Derived>::start(int size) const
DenseBase<Derived>::head(int size) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived>(derived(), 0, size);
@@ -186,16 +186,16 @@ DenseBase<Derived>::start(int size) const
*/
template<typename Derived>
inline VectorBlock<Derived>
DenseBase<Derived>::end(int size)
DenseBase<Derived>::tail(int size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived>(derived(), this->size() - size, size);
}
/** This is the const version of end(int).*/
/** This is the const version of tail(int).*/
template<typename Derived>
inline const VectorBlock<Derived>
DenseBase<Derived>::end(int size) const
DenseBase<Derived>::tail(int size) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived>(derived(), this->size() - size, size);
@@ -247,17 +247,17 @@ DenseBase<Derived>::segment(int start) const
template<typename Derived>
template<int Size>
inline VectorBlock<Derived,Size>
DenseBase<Derived>::start()
DenseBase<Derived>::head()
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived,Size>(derived(), 0);
}
/** This is the const version of start<int>().*/
/** This is the const version of head<int>().*/
template<typename Derived>
template<int Size>
inline const VectorBlock<Derived,Size>
DenseBase<Derived>::start() const
DenseBase<Derived>::head() const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived,Size>(derived(), 0);
@@ -277,17 +277,17 @@ DenseBase<Derived>::start() const
template<typename Derived>
template<int Size>
inline VectorBlock<Derived,Size>
DenseBase<Derived>::end()
DenseBase<Derived>::tail()
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived, Size>(derived(), size() - Size);
}
/** This is the const version of end<int>.*/
/** This is the const version of tail<int>.*/
template<typename Derived>
template<int Size>
inline const VectorBlock<Derived,Size>
DenseBase<Derived>::end() const
DenseBase<Derived>::tail() const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return VectorBlock<Derived, Size>(derived(), size() - Size);

View File

@@ -69,7 +69,7 @@ void ei_cache_friendly_product_colmajor_times_vector(
// How many coeffs of the result do we have to skip to be aligned.
// Here we assume data are at least aligned on the base scalar type.
int alignedStart = ei_alignmentOffset(res,size);
int alignedStart = ei_first_aligned(res,size);
int alignedSize = PacketSize>1 ? alignedStart + ((size-alignedStart) & ~PacketAlignedMask) : 0;
const int peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
@@ -79,7 +79,7 @@ void ei_cache_friendly_product_colmajor_times_vector(
: FirstAligned;
// we cannot assume the first element is aligned because of sub-matrices
const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
const int lhsAlignmentOffset = ei_first_aligned(lhs,size);
// find how many columns do we have to skip to be aligned with the result (if possible)
int skipColumns = 0;
@@ -282,7 +282,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
// How many coeffs of the result do we have to skip to be aligned.
// Here we assume data are at least aligned on the base scalar type
// if that's not the case then vectorization is discarded, see below.
int alignedStart = ei_alignmentOffset(rhs, size);
int alignedStart = ei_first_aligned(rhs, size);
int alignedSize = PacketSize>1 ? alignedStart + ((size-alignedStart) & ~PacketAlignedMask) : 0;
const int peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
@@ -292,7 +292,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
: FirstAligned;
// we cannot assume the first element is aligned because of sub-matrices
const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
const int lhsAlignmentOffset = ei_first_aligned(lhs,size);
// find how many rows do we have to skip to be aligned with rhs (if possible)
int skipRows = 0;

View File

@@ -313,7 +313,6 @@ struct ei_product_selfadjoint_matrix<Scalar,LhsStorageOrder,false,ConjugateLhs,
int size = cols;
ei_const_blas_data_mapper<Scalar, LhsStorageOrder> lhs(_lhs,lhsStride);
ei_const_blas_data_mapper<Scalar, RhsStorageOrder> rhs(_rhs,rhsStride);
if (ConjugateRhs)
alpha = ei_conj(alpha);

View File

@@ -86,7 +86,7 @@ static EIGEN_DONT_INLINE void ei_product_selfadjoint_vector(
size_t starti = FirstTriangular ? 0 : j+2;
size_t endi = FirstTriangular ? j : size;
size_t alignedEnd = starti;
size_t alignedStart = (starti) + ei_alignmentOffset(&res[starti], endi-starti);
size_t alignedStart = (starti) + ei_first_aligned(&res[starti], endi-starti);
alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
res[j] += cj0.pmul(A0[j], t0);

View File

@@ -41,8 +41,8 @@ struct ei_selfadjoint_rank2_update_selector<Scalar,UType,VType,LowerTriangular>
for (int i=0; i<size; ++i)
{
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+i, size-i) +=
(alpha * ei_conj(u.coeff(i))) * v.end(size-i)
+ (alpha * ei_conj(v.coeff(i))) * u.end(size-i);
(alpha * ei_conj(u.coeff(i))) * v.tail(size-i)
+ (alpha * ei_conj(v.coeff(i))) * u.tail(size-i);
}
}
};
@@ -55,8 +55,8 @@ struct ei_selfadjoint_rank2_update_selector<Scalar,UType,VType,UpperTriangular>
const int size = u.size();
for (int i=0; i<size; ++i)
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i, i+1) +=
(alpha * ei_conj(u.coeff(i))) * v.start(i+1)
+ (alpha * ei_conj(v.coeff(i))) * u.start(i+1);
(alpha * ei_conj(u.coeff(i))) * v.head(i+1)
+ (alpha * ei_conj(v.coeff(i))) * u.head(i+1);
}
};

View File

@@ -223,7 +223,8 @@ struct ei_blas_traits<Transpose<NestedXpr> >
typedef typename NestedXpr::Scalar Scalar;
typedef ei_blas_traits<NestedXpr> Base;
typedef Transpose<NestedXpr> XprType;
typedef Transpose<typename Base::_ExtractType> ExtractType;
typedef Transpose<typename Base::_ExtractType> ExtractType;
typedef Transpose<typename Base::_ExtractType> _ExtractType;
typedef typename ei_meta_if<int(Base::ActualAccess)==HasDirectAccess,
ExtractType,
typename ExtractType::PlainMatrixType

View File

@@ -209,27 +209,53 @@ template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *pt
ei_conditional_aligned_free<Align>(ptr);
}
/** \internal \returns the number of elements which have to be skipped to
* find the first 16-byte aligned element
/** \internal \returns the index of the first element of the array that is well aligned for vectorization.
*
* There is also the variant ei_alignmentOffset(const MatrixBase&, Integer) defined in Coeffs.h.
* \param array the address of the start of the array
* \param size the size of the array
*
* \note If no element of the array is well aligned, the size of the array is returned. Typically,
* for example with SSE, "well aligned" means 16-byte-aligned. If vectorization is disabled or if the
* packet size for the given scalar type is 1, then everything is considered well-aligned.
*
* \note If the scalar type is vectorizable, we rely on the following assumptions: sizeof(Scalar) is a
* power of 2, the packet size in bytes is also a power of 2, and is a multiple of sizeof(Scalar). On the
* other hand, we do not assume that the array address is a multiple of sizeof(Scalar), as that fails for
* example with Scalar=double on certain 32-bit platforms, see bug #79.
*
* There is also the variant ei_first_aligned(const MatrixBase&, Integer) defined in Coeffs.h.
*/
template<typename Scalar, typename Integer>
inline static Integer ei_alignmentOffset(const Scalar* ptr, Integer maxOffset)
inline static Integer ei_first_aligned(const Scalar* array, Integer size)
{
typedef typename ei_packet_traits<Scalar>::type Packet;
const Integer PacketSize = ei_packet_traits<Scalar>::size;
const Integer PacketAlignedMask = PacketSize-1;
const bool Vectorized = PacketSize>1;
return Vectorized
? std::min<Integer>( (PacketSize - (Integer((size_t(ptr)/sizeof(Scalar))) & PacketAlignedMask))
& PacketAlignedMask, maxOffset)
: 0;
enum { PacketSize = ei_packet_traits<Scalar>::size,
PacketAlignedMask = PacketSize-1
};
if(PacketSize==1)
{
// Either there is no vectorization, or a packet consists of exactly 1 scalar so that all elements
// of the array have the same aligment.
return 0;
}
else if(size_t(array) & (sizeof(Scalar)-1))
{
// There is vectorization for this scalar type, but the array is not aligned to the size of a single scalar.
// Consequently, no element of the array is well aligned.
return size;
}
else
{
return std::min<Integer>( (PacketSize - (Integer((size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
& PacketAlignedMask, size);
}
}
/** \internal
* ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
* on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
* on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and
* if stack allocation is supported by the platform (currently, this is linux only).
* Otherwise the memory is allocated on the heap.
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
* \code
@@ -381,10 +407,10 @@ public:
ei_aligned_free( p );
}
bool operator!=(const aligned_allocator<T>& other) const
bool operator!=(const aligned_allocator<T>& ) const
{ return false; }
bool operator==(const aligned_allocator<T>& other) const
bool operator==(const aligned_allocator<T>& ) const
{ return true; }
};

View File

@@ -109,23 +109,6 @@ template<int _Rows, int _Cols> struct ei_size_at_compile_time
* whereas ei_eval is a const reference in the case of a matrix
*/
// template<typename Derived> class MatrixBase;
// template<typename Derived> class ArrayBase;
// template<typename Object> struct ei_is_matrix_or_array
// {
// struct is_matrix {int a[1];};
// struct is_array {int a[2];};
// struct is_none {int a[3];};
//
// template<typename T>
// static is_matrix testBaseClass(const MatrixBase<T>*);
// template<typename T>
// static is_array testBaseClass(const ArrayBase<T>*);
// // static is_none testBaseClass(...);
//
// enum {BaseClassType = sizeof(testBaseClass(static_cast<const Object*>(0)))};
// };
template<typename T, typename StorageType = typename ei_traits<T>::StorageType> class ei_plain_matrix_type;
template<typename T, typename BaseClassType> struct ei_plain_matrix_type_dense;
template<typename T> struct ei_plain_matrix_type<T,Dense>