* updated the assignement operator macro so that overloads

in MatrixBase work
* removed product_selector and cleaned Product.h a bit
* cleaned Assign.h a bit
This commit is contained in:
Gael Guennebaud 2008-05-28 22:56:19 +00:00
parent 8711e26c8a
commit c1559d3079
3 changed files with 16 additions and 128 deletions

View File

@ -112,9 +112,6 @@ template<typename OtherDerived>
inline Derived& MatrixBase<Derived> inline Derived& MatrixBase<Derived>
::lazyAssign(const MatrixBase<OtherDerived>& other) ::lazyAssign(const MatrixBase<OtherDerived>& other)
{ {
// std::cout << typeid(OtherDerived).name() << "\n";
// std::cout << "lazyAssign = " << (Derived::Flags&VectorizableBit) << " " << (OtherDerived::Flags&VectorizableBit) << "\n";
// std::cout << __PRETTY_FUNCTION__ << std::endl;
ei_assignment_impl<Derived, OtherDerived>::execute(derived(),other.derived()); ei_assignment_impl<Derived, OtherDerived>::execute(derived(),other.derived());
return derived(); return derived();
} }
@ -186,7 +183,6 @@ struct ei_assignment_impl<Derived, OtherDerived, true>
const bool unroll = Derived::SizeAtCompileTime * OtherDerived::CoeffReadCost <= EIGEN_UNROLLING_LIMIT; const bool unroll = Derived::SizeAtCompileTime * OtherDerived::CoeffReadCost <= EIGEN_UNROLLING_LIMIT;
if(unroll) if(unroll)
{ {
// std::cout << "vectorized unrolled\n";
ei_matrix_assignment_packet_unroller ei_matrix_assignment_packet_unroller
<Derived, OtherDerived, <Derived, OtherDerived,
unroll && int(Derived::SizeAtCompileTime)>=int(ei_packet_traits<typename Derived::Scalar>::size) unroll && int(Derived::SizeAtCompileTime)>=int(ei_packet_traits<typename Derived::Scalar>::size)
@ -201,7 +197,6 @@ struct ei_assignment_impl<Derived, OtherDerived, true>
&& (Derived::ColsAtCompileTime==Dynamic && (Derived::ColsAtCompileTime==Dynamic
|| Derived::ColsAtCompileTime%ei_packet_traits<typename Derived::Scalar>::size!=0)) || Derived::ColsAtCompileTime%ei_packet_traits<typename Derived::Scalar>::size!=0))
{ {
// std::cout << "vectorized linear row major\n";
const int size = dst.rows() * dst.cols(); const int size = dst.rows() * dst.cols();
const int alignedSize = (size/ei_packet_traits<typename Derived::Scalar>::size)*ei_packet_traits<typename Derived::Scalar>::size; const int alignedSize = (size/ei_packet_traits<typename Derived::Scalar>::size)*ei_packet_traits<typename Derived::Scalar>::size;
int index = 0; int index = 0;
@ -218,7 +213,6 @@ struct ei_assignment_impl<Derived, OtherDerived, true>
} }
else else
{ {
// std::cout << "vectorized normal row major\n";
for(int i = 0; i < dst.rows(); i++) for(int i = 0; i < dst.rows(); i++)
for(int j = 0; j < dst.cols(); j+=ei_packet_traits<typename Derived::Scalar>::size) for(int j = 0; j < dst.cols(); j+=ei_packet_traits<typename Derived::Scalar>::size)
dst.template writePacketCoeff<Aligned>(i, j, src.template packetCoeff<Aligned>(i, j)); dst.template writePacketCoeff<Aligned>(i, j, src.template packetCoeff<Aligned>(i, j));
@ -230,7 +224,6 @@ struct ei_assignment_impl<Derived, OtherDerived, true>
&& ( Derived::RowsAtCompileTime==Dynamic && ( Derived::RowsAtCompileTime==Dynamic
|| Derived::RowsAtCompileTime%ei_packet_traits<typename Derived::Scalar>::size!=0)) || Derived::RowsAtCompileTime%ei_packet_traits<typename Derived::Scalar>::size!=0))
{ {
// std::cout << "vectorized linear col major\n";
const int size = dst.rows() * dst.cols(); const int size = dst.rows() * dst.cols();
const int alignedSize = (size/ei_packet_traits<typename Derived::Scalar>::size)*ei_packet_traits<typename Derived::Scalar>::size; const int alignedSize = (size/ei_packet_traits<typename Derived::Scalar>::size)*ei_packet_traits<typename Derived::Scalar>::size;
int index = 0; int index = 0;
@ -247,7 +240,6 @@ struct ei_assignment_impl<Derived, OtherDerived, true>
} }
else else
{ {
// std::cout << "vectorized normal col major\n";
for(int j = 0; j < dst.cols(); j++) for(int j = 0; j < dst.cols(); j++)
for(int i = 0; i < dst.rows(); i+=ei_packet_traits<typename Derived::Scalar>::size) for(int i = 0; i < dst.rows(); i+=ei_packet_traits<typename Derived::Scalar>::size)
dst.template writePacketCoeff<Aligned>(i, j, src.template packetCoeff<Aligned>(i, j)); dst.template writePacketCoeff<Aligned>(i, j, src.template packetCoeff<Aligned>(i, j));

View File

@ -134,8 +134,6 @@ template<typename Product> struct ProductPacketCoeffImpl<Product, false> {
* This class represents an expression of the product of two matrices. * This class represents an expression of the product of two matrices.
* It is the return type of the operator* between matrices, and most of the time * It is the return type of the operator* between matrices, and most of the time
* this is the only way it is used. * this is the only way it is used.
*
* \sa class Sum, class Difference
*/ */
template<typename Lhs, typename Rhs> struct ei_product_eval_mode template<typename Lhs, typename Rhs> struct ei_product_eval_mode
{ {
@ -162,6 +160,7 @@ template<typename T> class ei_product_eval_to_column_major
ei_traits<T>::MaxColsAtCompileTime> type; ei_traits<T>::MaxColsAtCompileTime> type;
}; };
// as ei_nested, but evaluate to a column-major matrix if an evaluation is required
template<typename T, int n=1> struct ei_product_nested_rhs template<typename T, int n=1> struct ei_product_nested_rhs
{ {
typedef typename ei_meta_if< typedef typename ei_meta_if<
@ -176,51 +175,11 @@ template<typename T, int n=1> struct ei_product_nested_rhs
>::ret type; >::ret type;
}; };
// template<typename T, int n=1> struct ei_product_nested_lhs
// {
// typedef typename ei_meta_if<
// ei_must_nest_by_value<T>::ret && (int(ei_traits<T>::Flags) & DirectAccessBit),
// T,
// typename ei_meta_if<
// int(ei_traits<T>::Flags) & EvalBeforeNestingBit
// || (!(int(ei_traits<T>::Flags) & DirectAccessBit))
// || (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost) < (n-1) * int(T::CoeffReadCost),
// typename ei_eval<T>::type,
// const T&
// >::ret
// >::ret type;
// };
template<typename T> struct ei_product_copy_rhs
{
typedef typename ei_meta_if<
(ei_traits<T>::Flags & RowMajorBit)
|| (!(ei_traits<T>::Flags & DirectAccessBit)),
typename ei_product_eval_to_column_major<T>::type,
const T&
>::ret type;
};
template<typename T> struct ei_product_copy_lhs
{
typedef typename ei_meta_if<
(!(int(ei_traits<T>::Flags) & DirectAccessBit)),
typename ei_eval<T>::type,
const T&
>::ret type;
};
template<typename Lhs, typename Rhs, int EvalMode> template<typename Lhs, typename Rhs, int EvalMode>
struct ei_traits<Product<Lhs, Rhs, EvalMode> > struct ei_traits<Product<Lhs, Rhs, EvalMode> >
{ {
typedef typename Lhs::Scalar Scalar; typedef typename Lhs::Scalar Scalar;
// the cache friendly product evals lhs once only typedef typename ei_nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
// FIXME what to do if we chose to dynamically call the normal product from the cache friendly one for small matrices ?
typedef /*typename ei_meta_if<EvalMode==CacheFriendlyProduct,*/
// typename ei_product_nested_lhs<Lhs,1>::type,
typename ei_nested<Lhs,Rhs::ColsAtCompileTime>::type/*>::ret*/ LhsNested;
// NOTE that rhs must be ColumnMajor, so we might need a special nested type calculation
typedef typename ei_meta_if<EvalMode==CacheFriendlyProduct, typedef typename ei_meta_if<EvalMode==CacheFriendlyProduct,
typename ei_product_nested_rhs<Rhs,Lhs::RowsAtCompileTime>::type, typename ei_product_nested_rhs<Rhs,Lhs::RowsAtCompileTime>::type,
typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type>::ret RhsNested; typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type>::ret RhsNested;
@ -385,7 +344,6 @@ template<typename Lhs,typename Rhs>
inline Derived& inline Derived&
MatrixBase<Derived>::operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProduct>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) MatrixBase<Derived>::operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProduct>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
{ {
std::cout << "_cacheFriendlyEvalAndAdd\n";
other._expression()._cacheFriendlyEvalAndAdd(const_cast_derived()); other._expression()._cacheFriendlyEvalAndAdd(const_cast_derived());
return derived(); return derived();
} }
@ -398,92 +356,35 @@ inline Derived& MatrixBase<Derived>::lazyAssign(const Product<Lhs,Rhs,CacheFrien
return derived(); return derived();
} }
template<typename Lhs, typename Rhs, int EvalMode, typename DestDerived, bool DirectAccess> template<typename T> struct ei_product_copy_rhs
struct ei_cache_friendly_selector
{ {
typedef Product<Lhs,Rhs,EvalMode> Prod; typedef typename ei_meta_if<
typedef typename Prod::_LhsNested _LhsNested; (ei_traits<T>::Flags & RowMajorBit)
typedef typename Prod::_RhsNested _RhsNested; || (!(ei_traits<T>::Flags & DirectAccessBit)),
typedef typename Prod::Scalar Scalar; typename ei_product_eval_to_column_major<T>::type,
static inline void eval(const Prod& product, DestDerived& res) const T&
{ >::ret type;
if ( product._rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& product._cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& product.m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
)
{
res.setZero();
// typename ei_product_copy_lhs<>::type
ei_cache_friendly_product<Scalar>(
product._rows(), product._cols(), product.m_lhs.cols(),
_LhsNested::Flags&RowMajorBit, &(product.m_lhs.const_cast_derived().coeffRef(0,0)), product.m_lhs.stride(),
_RhsNested::Flags&RowMajorBit, &(product.m_rhs.const_cast_derived().coeffRef(0,0)), product.m_rhs.stride(),
Prod::Flags&RowMajorBit, &(res.coeffRef(0,0)), res.stride()
);
}
else
{
res = Product<_LhsNested,_RhsNested,NormalProduct>(product.m_lhs, product.m_rhs).lazy();
}
}
static inline void eval_and_add(const Prod& product, DestDerived& res)
{
if ( product._rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& product._cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& product.m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
)
{
ei_cache_friendly_product<Scalar>(
product._rows(), product._cols(), product.m_lhs.cols(),
_LhsNested::Flags&RowMajorBit, &(product.m_lhs.const_cast_derived().coeffRef(0,0)), product.m_lhs.stride(),
_RhsNested::Flags&RowMajorBit, &(product.m_rhs.const_cast_derived().coeffRef(0,0)), product.m_rhs.stride(),
Prod::Flags&RowMajorBit, &(res.coeffRef(0,0)), res.stride()
);
}
else
{
res += Product<_LhsNested,_RhsNested,NormalProduct>(product.m_lhs, product.m_rhs).lazy();
}
}
}; };
template<typename Lhs, typename Rhs, int EvalMode, typename DestDerived> template<typename T> struct ei_product_copy_lhs
struct ei_cache_friendly_selector<Lhs,Rhs,EvalMode,DestDerived,false>
{ {
typedef Product<Lhs,Rhs,EvalMode> Prod; typedef typename ei_meta_if<
typedef typename Prod::_LhsNested _LhsNested; (!(int(ei_traits<T>::Flags) & DirectAccessBit)),
typedef typename Prod::_RhsNested _RhsNested; typename ei_eval<T>::type,
typedef typename Prod::Scalar Scalar; const T&
static inline void eval(const Prod& product, DestDerived& res) >::ret type;
{
res = Product<_LhsNested,_RhsNested,NormalProduct>(product.m_lhs, product.m_rhs).lazy();
}
static inline void eval_and_add(const Prod& product, DestDerived& res)
{
res += Product<_LhsNested,_RhsNested,NormalProduct>(product.m_lhs, product.m_rhs).lazy();
}
}; };
template<typename Lhs, typename Rhs, int EvalMode> template<typename Lhs, typename Rhs, int EvalMode>
template<typename DestDerived> template<typename DestDerived>
inline void Product<Lhs,Rhs,EvalMode>::_cacheFriendlyEval(DestDerived& res) const inline void Product<Lhs,Rhs,EvalMode>::_cacheFriendlyEval(DestDerived& res) const
{ {
// ei_cache_friendly_selector<Lhs,Rhs,EvalMode,DestDerived,
// _LhsNested::Flags&_RhsNested::Flags&DirectAccessBit>
// ::eval(*this, res);
if ( _rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD if ( _rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& _cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD && _cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD && m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
) )
{ {
res.setZero(); res.setZero();
// typedef typename ei_eval<_LhsNested>::type LhsCopy;
// typedef typename ei_product_eval_to_column_major<_RhsNested>::type RhsCopy;
typedef typename ei_product_copy_lhs<_LhsNested>::type LhsCopy; typedef typename ei_product_copy_lhs<_LhsNested>::type LhsCopy;
typedef typename ei_unref<LhsCopy>::type _LhsCopy; typedef typename ei_unref<LhsCopy>::type _LhsCopy;
typedef typename ei_product_copy_rhs<_RhsNested>::type RhsCopy; typedef typename ei_product_copy_rhs<_RhsNested>::type RhsCopy;
@ -501,17 +402,12 @@ inline void Product<Lhs,Rhs,EvalMode>::_cacheFriendlyEval(DestDerived& res) cons
{ {
res = Product<_LhsNested,_RhsNested,NormalProduct>(m_lhs, m_rhs).lazy(); res = Product<_LhsNested,_RhsNested,NormalProduct>(m_lhs, m_rhs).lazy();
} }
} }
template<typename Lhs, typename Rhs, int EvalMode> template<typename Lhs, typename Rhs, int EvalMode>
template<typename DestDerived> template<typename DestDerived>
inline void Product<Lhs,Rhs,EvalMode>::_cacheFriendlyEvalAndAdd(DestDerived& res) const inline void Product<Lhs,Rhs,EvalMode>::_cacheFriendlyEvalAndAdd(DestDerived& res) const
{ {
std::cout << "_cacheFriendlyEvalAndAdd\n";
// ei_cache_friendly_selector<Lhs,Rhs,EvalMode,DestDerived,
// _LhsNested::Flags&_RhsNested::Flags&DirectAccessBit>
// ::eval_and_add(*this, res);
if ( _rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD if ( _rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& _cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD && _cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD && m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD

View File

@ -107,7 +107,7 @@ using Eigen::MatrixBase;
template<typename OtherDerived> \ template<typename OtherDerived> \
Derived& operator Op(const MatrixBase<OtherDerived>& other) \ Derived& operator Op(const MatrixBase<OtherDerived>& other) \
{ \ { \
return Eigen::MatrixBase<Derived>::operator Op(other); \ return Eigen::MatrixBase<Derived>::operator Op(other.derived()); \
} \ } \
Derived& operator Op(const Derived& other) \ Derived& operator Op(const Derived& other) \
{ \ { \