Enable use of evaluators for noalias and lazyProduct, add conversion to scalar for inner products

This commit is contained in:
Gael Guennebaud 2013-12-03 17:17:53 +01:00
parent f0b82c3ab9
commit 6c5e915e9a
10 changed files with 103 additions and 22 deletions

View File

@ -53,11 +53,7 @@ struct storage_kind_to_shape<Sparse> {
};
*/
template<typename T> struct evaluator_traits;
template< typename T,
typename Kind = typename evaluator_traits<T>::Kind,
typename Scalar = typename T::Scalar> struct evaluator;
template< typename T,
typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,

View File

@ -623,7 +623,7 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
return Product<Derived, OtherDerived>(derived(), other.derived());
}
#else
#else // EIGEN_TEST_EVALUATORS
template<typename Derived>
template<typename OtherDerived>
inline const typename ProductReturnType<Derived, OtherDerived>::Type
@ -653,9 +653,10 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
#endif
return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
}
#endif
#endif // EIGEN_TEST_EVALUATORS
#endif // __CUDACC__
#endif
/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation.
*
* The returned product will behave like any other expressions: the coefficients of the product will be
@ -667,6 +668,31 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
*
* \sa operator*(const MatrixBase&)
*/
#ifdef EIGEN_TEST_EVALUATORS
template<typename Derived>
template<typename OtherDerived>
const Product<Derived,OtherDerived,LazyProduct>
MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
{
enum {
ProductIsValid = Derived::ColsAtCompileTime==Dynamic
|| OtherDerived::RowsAtCompileTime==Dynamic
|| int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
};
// note to the lost user:
// * for a dot product use: v1.dot(v2)
// * for a coeff-wise product use: v1.cwiseProduct(v2)
EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
return Product<Derived,OtherDerived,LazyProduct>(derived(), other.derived());
}
#else // EIGEN_TEST_EVALUATORS
template<typename Derived>
template<typename OtherDerived>
const typename LazyProductReturnType<Derived,OtherDerived>::Type
@ -690,6 +716,7 @@ MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
}
#endif // EIGEN_TEST_EVALUATORS
} // end namespace Eigen

View File

@ -199,7 +199,11 @@ template<typename Derived> class MatrixBase
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
#ifdef EIGEN_TEST_EVALUATORS
const Product<Derived,OtherDerived,LazyProduct>
#else
const typename LazyProductReturnType<Derived,OtherDerived>::Type
#endif
lazyProduct(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>

View File

@ -34,6 +34,33 @@ class NoAlias
typedef typename ExpressionType::Scalar Scalar;
NoAlias(ExpressionType& expression) : m_expression(expression) {}
#ifdef EIGEN_TEST_EVALUATORS
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other)
{
call_assignment(*this, other.derived(), internal::assign_op<Scalar>());
return m_expression;
}
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other)
{
call_assignment(*this, other.derived(), internal::add_assign_op<Scalar>());
return m_expression;
}
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other)
{
call_assignment(*this, other.derived(), internal::sub_assign_op<Scalar>());
return m_expression;
}
#else
/** Behaves like MatrixBase::lazyAssign(other)
* \sa MatrixBase::lazyAssign() */
@ -91,6 +118,8 @@ class NoAlias
template<typename OtherDerived>
ExpressionType& operator=(const ReturnByValue<OtherDerived>& func)
{ return m_expression = func; }
#endif
#endif
EIGEN_DEVICE_FUNC

View File

@ -79,6 +79,12 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
const LhsNestedCleaned& lhs() const { return m_lhs; }
const RhsNestedCleaned& rhs() const { return m_rhs; }
/** Convertion to scalar for inner-products */
operator const Scalar() const {
EIGEN_STATIC_ASSERT(SizeAtCompileTime==1, IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY);
return typename internal::evaluator<Product>::type(*this).coeff(0,0);
}
protected:

View File

@ -209,12 +209,12 @@ struct dense_product_impl<Lhs,Rhs,GemmProduct> : dense_product_impl_base<Lhs,Rhs
{
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
template<typename Dest>
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
{
// TODO bypass GeneralProduct class
GeneralProduct<Lhs, Rhs, GemmProduct>(lhs,rhs).scaleAndAddTo(dst, alpha);
}
// template<typename Dest>
// static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
// {
// // TODO bypass GeneralProduct class
// GeneralProduct<Lhs, Rhs, GemmProduct>(lhs,rhs).scaleAndAddTo(dst, alpha);
// }
};
template<typename Lhs, typename Rhs>
@ -225,22 +225,28 @@ struct dense_product_impl<Lhs,Rhs,CoeffBasedProductMode>
template<typename Dst>
static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
{
// TODO: use the following instead of calling call_assignment
// TODO: use the following instead of calling call_assignment, same for the other methods
// dst = lazyprod(lhs,rhs);
call_assignment(dst, lazyprod(lhs,rhs), internal::assign_op<Scalar>());
}
template<typename Dst>
static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
{ dst += lazyprod(lhs,rhs); }
{
// dst += lazyprod(lhs,rhs);
call_assignment(dst, lazyprod(lhs,rhs), internal::add_assign_op<Scalar>());
}
template<typename Dst>
static inline void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
{ dst -= lazyprod(lhs,rhs); }
{
// dst -= lazyprod(lhs,rhs);
call_assignment(dst, lazyprod(lhs,rhs), internal::sub_assign_op<Scalar>());
}
template<typename Dst>
static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
{ dst += alpha * lazyprod(lhs,rhs); }
// template<typename Dst>
// static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
// { dst += alpha * lazyprod(lhs,rhs); }
};
template<typename Lhs, typename Rhs>
@ -286,7 +292,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
CoeffReadCost = traits<CoeffBasedProductType>::CoeffReadCost,
Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
CanVectorizeInner = traits<CoeffBasedProductType>::CanVectorizeInner,
Flags = CoeffBasedProductType::Flags
Flags = traits<CoeffBasedProductType>::Flags
};
typedef typename evaluator<Lhs>::type LhsEtorType;

View File

@ -14,7 +14,7 @@
namespace Eigen {
namespace internal {
/*********************************************************************************
* Coefficient based product implementation.
* It is designed for the following use cases:
@ -110,6 +110,8 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
} // end namespace internal
#ifndef EIGEN_TEST_EVALUATORS
template<typename LhsNested, typename RhsNested, int NestingFlags>
class CoeffBasedProduct
: internal::no_assignment_operator,
@ -447,6 +449,8 @@ struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
} // end namespace internal
#endif // EIGEN_TEST_EVALUATORS
} // end namespace Eigen
#endif // EIGEN_COEFFBASED_PRODUCT_H

View File

@ -36,6 +36,12 @@ template<typename Derived> struct accessors_level
};
};
template<typename T> struct evaluator_traits;
template< typename T,
typename Kind = typename evaluator_traits<T>::Kind,
typename Scalar = typename T::Scalar> struct evaluator;
} // end namespace internal
template<typename T> struct NumTraits;

View File

@ -90,7 +90,8 @@
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED,
THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE,
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG,
IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY
};
};

View File

@ -66,6 +66,8 @@ namespace Eigen
static bool g_has_set_repeat, g_has_set_seed;
}
#define TRACK std::cerr << __FILE__ << " " << __LINE__ << std::endl
#define EI_PP_MAKE_STRING2(S) #S
#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)