mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-27 07:29:52 +08:00
Implement A.noalias() = B * C without temporaries
* Wrap expression inside EvalToTemp in copy_using_evaluators() if we assume aliasing for that expression (that is, for products) * Remove temporary kludge of evaluating expression to temporary in AllAtOnce traversal * Implement EvalToTemp expression object
This commit is contained in:
parent
d0b873822f
commit
746378868a
@ -617,12 +617,8 @@ struct copy_using_evaluator_impl<DstXprType, SrcXprType, AllAtOnceTraversal, NoU
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
|
||||
// Evaluate rhs in temporary to prevent aliasing problems in a = a * a;
|
||||
// TODO: Be smarter about this
|
||||
// TODO: Do not pass the xpr object to evalTo()
|
||||
typename DstXprType::PlainObject tmp;
|
||||
typename evaluator<typename DstXprType::PlainObject>::type tmpEvaluator(tmp);
|
||||
srcEvaluator.evalTo(tmpEvaluator, tmp);
|
||||
copy_using_evaluator(dst, tmp);
|
||||
srcEvaluator.evalTo(dstEvaluator, dst);
|
||||
}
|
||||
};
|
||||
|
||||
@ -640,11 +636,33 @@ const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& d
|
||||
return noalias_copy_using_evaluator(dst.expression(), src.derived());
|
||||
}
|
||||
|
||||
template<typename XprType, int AssumeAliasing = evaluator_traits<XprType>::AssumeAliasing>
|
||||
struct AddEvalIfAssumingAliasing;
|
||||
|
||||
template<typename XprType>
|
||||
struct AddEvalIfAssumingAliasing<XprType, 0>
|
||||
{
|
||||
static const XprType& run(const XprType& xpr)
|
||||
{
|
||||
return xpr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename XprType>
|
||||
struct AddEvalIfAssumingAliasing<XprType, 1>
|
||||
{
|
||||
static const EvalToTemp<XprType> run(const XprType& xpr)
|
||||
{
|
||||
return EvalToTemp<XprType>(xpr);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DstXprType, typename SrcXprType>
|
||||
EIGEN_STRONG_INLINE
|
||||
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
|
||||
{
|
||||
return noalias_copy_using_evaluator(dst.const_cast_derived(), src.derived());
|
||||
return noalias_copy_using_evaluator(dst.const_cast_derived(),
|
||||
AddEvalIfAssumingAliasing<SrcXprType>::run(src.derived()));
|
||||
}
|
||||
|
||||
template<typename DstXprType, typename SrcXprType>
|
||||
|
@ -40,6 +40,10 @@ struct evaluator_traits
|
||||
// 1 if evaluator_impl<T>::evalTo() exists
|
||||
// 0 if evaluator_impl<T> allows coefficient-based access
|
||||
static const int HasEvalTo = 0;
|
||||
|
||||
// 1 if assignment A = B assumes aliasing when B is of type T and thus B needs to be evaluated into a
|
||||
// temporary; 0 if not.
|
||||
static const int AssumeAliasing = 0;
|
||||
};
|
||||
|
||||
// expression class for evaluating nested expression to a temporary
|
||||
@ -245,17 +249,62 @@ struct evaluator_impl<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
||||
|
||||
// -------------------- EvalToTemp --------------------
|
||||
|
||||
template<typename ArgType>
|
||||
struct traits<EvalToTemp<ArgType> >
|
||||
: public traits<ArgType>
|
||||
{ };
|
||||
|
||||
template<typename ArgType>
|
||||
class EvalToTemp
|
||||
: public dense_xpr_base<EvalToTemp<ArgType> >::type
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename dense_xpr_base<EvalToTemp>::type Base;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
|
||||
|
||||
EvalToTemp(const ArgType& arg)
|
||||
: m_arg(arg)
|
||||
{ }
|
||||
|
||||
const ArgType& arg() const
|
||||
{
|
||||
return m_arg;
|
||||
}
|
||||
|
||||
Index rows() const
|
||||
{
|
||||
return m_arg.rows();
|
||||
}
|
||||
|
||||
Index cols() const
|
||||
{
|
||||
return m_arg.cols();
|
||||
}
|
||||
|
||||
private:
|
||||
const ArgType& m_arg;
|
||||
};
|
||||
|
||||
template<typename ArgType>
|
||||
struct evaluator_impl<EvalToTemp<ArgType> >
|
||||
: evaluator_impl<typename ArgType::PlainObject>
|
||||
{
|
||||
typedef EvalToTemp<ArgType> XprType;
|
||||
typedef typename ArgType::PlainObject PlainObject;
|
||||
typedef evaluator_impl<PlainObject> BaseType;
|
||||
|
||||
evaluator_impl(const XprType& xpr)
|
||||
: BaseType(m_result)
|
||||
{
|
||||
noalias_copy_using_evaluator(m_result, xpr.arg());
|
||||
};
|
||||
|
||||
// this constructor is used when nesting an EvalTo evaluator in another evaluator
|
||||
evaluator_impl(const ArgType& arg)
|
||||
: BaseType(m_result)
|
||||
{
|
||||
copy_using_evaluator(m_result, arg);
|
||||
noalias_copy_using_evaluator(m_result, arg);
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -56,7 +56,9 @@ struct product_evaluator_traits_dispatcher;
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct evaluator_traits<Product<Lhs, Rhs> >
|
||||
: product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, typename ProductReturnType<Lhs, Rhs>::Type>
|
||||
{ };
|
||||
{
|
||||
static const int AssumeAliasing = 1;
|
||||
};
|
||||
|
||||
// Case 1: Evaluate all at once
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user