mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
merge and add start/end to Eigen2Support
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user