mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-12 03:39:01 +08:00
Evaluator: introduce the main Assignment class, add call_assignment to bypass NoAlias and AssumeAliasing, and some bits of cleaning
This commit is contained in:
parent
c550a0e634
commit
230f5c3aa9
@ -514,7 +514,7 @@ struct dense_assignment_loop<Kernel, AllAtOnceTraversal, NoUnrolling>
|
|||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Part 4 : Generic Assignment routine
|
* Part 4 : Generic dense assignment kernel
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// This class generalize the assignment of a coefficient (or packet) from one dense evaluator
|
// This class generalize the assignment of a coefficient (or packet) from one dense evaluator
|
||||||
@ -617,6 +617,10 @@ protected:
|
|||||||
DstXprType& m_dstExpr;
|
DstXprType& m_dstExpr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Part 5 : Entry point for dense rectangular assignment
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
template<typename DstXprType, typename SrcXprType, typename Functor>
|
||||||
void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
|
void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||||
{
|
{
|
||||||
@ -645,195 +649,81 @@ void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Part 5 : Entry points
|
* Part 6 : Generic assignment
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// Based on DenseBase::LazyAssign()
|
|
||||||
// The following functions are just for testing and they are meant to be moved to operator= and the likes.
|
|
||||||
|
|
||||||
template<typename DstXprType, template <typename> class StorageBase, typename SrcXprType>
|
// An evaluator must define its shape. It can be one of the following:
|
||||||
EIGEN_STRONG_INLINE
|
struct DenseShape {};
|
||||||
const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& dst,
|
struct DiagonalShape {};
|
||||||
const EigenBase<SrcXprType>& src)
|
struct BandShape {};
|
||||||
|
struct TriangularShape {};
|
||||||
|
struct SelfAdjointShape {};
|
||||||
|
struct SparseShape {};
|
||||||
|
|
||||||
|
|
||||||
|
// Based on the respective shapes of the destination and source,
|
||||||
|
// the class AssignmentKind determine the kind of assignment mechanism.
|
||||||
|
// AssignmentKind must define a Kind typedef.
|
||||||
|
template<int DstShape, int SrcShape> struct AssignmentKind;
|
||||||
|
|
||||||
|
// AssignmentKind<.,.>::Kind can be one of the following:
|
||||||
|
struct Dense2Dense {};
|
||||||
|
struct Triangular2Triangular {};
|
||||||
|
// struct Diagonal2Diagonal {}; // <=> Dense2Dense
|
||||||
|
struct Sparse2Dense {};
|
||||||
|
struct Sparse2Sparse {};
|
||||||
|
|
||||||
|
// This is the main assignment class
|
||||||
|
template< typename DstXprType, typename SrcXprType, typename Functor,
|
||||||
|
typename Kind = Dense2Dense,//AssignmentKind< evaluator<A>::Shape , evaluator<B>::Shape >::Kind,
|
||||||
|
typename Scalar = typename DstXprType::Scalar>
|
||||||
|
struct Assignment;
|
||||||
|
|
||||||
|
|
||||||
|
// The only purpose of this call_assignment() function is to deal with noalias() / AssumeAliasing.
|
||||||
|
// Indeed, I (Gael) think that this concept of AssumeAliasing was a mistake, and it makes thing quite complicated.
|
||||||
|
// So this intermediate function removes everything related to AssumeAliasing such that Assignment
|
||||||
|
// does not has to bother about these annoying details.
|
||||||
|
|
||||||
|
template<typename Dst, typename Src, typename Func>
|
||||||
|
void call_assignment(Dst& dst, const Src& src, const Func& func)
|
||||||
{
|
{
|
||||||
return noalias_copy_using_evaluator(dst.expression(), src.derived(), internal::assign_op<typename DstXprType::Scalar>());
|
typedef typename internal::conditional<evaluator_traits<Src>::AssumeAliasing==1, EvalToTemp<Src>, Src>::type ActualSrc;
|
||||||
|
Assignment<Dst,ActualSrc,Func>::run(dst, src, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename XprType, int AssumeAliasing = evaluator_traits<XprType>::AssumeAliasing>
|
// by-pass AssumeAliasing
|
||||||
struct AddEvalIfAssumingAliasing;
|
template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
|
||||||
|
void call_assignment(const NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
|
||||||
template<typename XprType>
|
|
||||||
struct AddEvalIfAssumingAliasing<XprType, 0>
|
|
||||||
{
|
{
|
||||||
static const XprType& run(const XprType& xpr)
|
Assignment<Dst,Src,Func>::run(dst.expression(), src, func);
|
||||||
{
|
|
||||||
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, typename Functor>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
|
|
||||||
{
|
|
||||||
return noalias_copy_using_evaluator(dst.const_cast_derived(),
|
|
||||||
AddEvalIfAssumingAliasing<SrcXprType>::run(src.derived()),
|
|
||||||
func
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this mimics operator=
|
// Generic Dense to Dense assignment
|
||||||
template<typename DstXprType, typename SrcXprType>
|
template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
|
||||||
EIGEN_STRONG_INLINE
|
struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Scalar>
|
||||||
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
|
|
||||||
{
|
{
|
||||||
return copy_using_evaluator(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar>());
|
static void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& noalias_copy_using_evaluator(const PlainObjectBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
|
|
||||||
{
|
|
||||||
#ifdef EIGEN_DEBUG_ASSIGN
|
|
||||||
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
|
|
||||||
#endif
|
|
||||||
#ifdef EIGEN_NO_AUTOMATIC_RESIZING
|
|
||||||
eigen_assert((dst.size()==0 || (IsVectorAtCompileTime ? (dst.size() == src.size())
|
|
||||||
: (dst.rows() == src.rows() && dst.cols() == src.cols())))
|
|
||||||
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
|
|
||||||
#else
|
|
||||||
dst.const_cast_derived().resizeLike(src.derived());
|
|
||||||
#endif
|
|
||||||
call_dense_assignment_loop(dst.const_cast_derived(), src.derived(), func);
|
|
||||||
return dst.derived();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& noalias_copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
|
|
||||||
{
|
|
||||||
call_dense_assignment_loop(dst.const_cast_derived(), src.derived(), func);
|
|
||||||
return dst.derived();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on DenseBase::swap()
|
|
||||||
// TODO: Check whether we need to do something special for swapping two
|
|
||||||
// Arrays or Matrices. (Jitse)
|
|
||||||
|
|
||||||
// Overload default assignPacket behavior for swapping them
|
|
||||||
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT>
|
|
||||||
class swap_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> >
|
|
||||||
{
|
|
||||||
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> > Base;
|
|
||||||
typedef typename DstEvaluatorTypeT::PacketScalar PacketScalar;
|
|
||||||
using Base::m_dst;
|
|
||||||
using Base::m_src;
|
|
||||||
using Base::m_functor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename Base::Scalar Scalar;
|
|
||||||
typedef typename Base::Index Index;
|
|
||||||
typedef typename Base::DstXprType DstXprType;
|
|
||||||
|
|
||||||
swap_kernel(DstEvaluatorTypeT &dst, const SrcEvaluatorTypeT &src, DstXprType& dstExpr)
|
|
||||||
: Base(dst, src, swap_assign_op<Scalar>(), dstExpr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<int StoreMode, int LoadMode>
|
|
||||||
void assignPacket(Index row, Index col)
|
|
||||||
{
|
{
|
||||||
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(row,col), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(row,col));
|
// TODO check whether this is the right place to perform these checks:
|
||||||
}
|
enum{
|
||||||
|
SameType = internal::is_same<typename DstXprType::Scalar,typename SrcXprType::Scalar>::value
|
||||||
template<int StoreMode, int LoadMode>
|
};
|
||||||
void assignPacket(Index index)
|
|
||||||
{
|
|
||||||
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(index), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I mean no CRTP (Gael)
|
|
||||||
template<int StoreMode, int LoadMode>
|
|
||||||
void assignPacketByOuterInner(Index outer, Index inner)
|
|
||||||
{
|
|
||||||
Index row = Base::rowIndexByOuterInner(outer, inner);
|
|
||||||
Index col = Base::colIndexByOuterInner(outer, inner);
|
|
||||||
assignPacket<StoreMode,LoadMode>(row, col);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void swap_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
|
||||||
{
|
|
||||||
// TODO there is too much redundancy with call_dense_assignment_loop
|
|
||||||
|
|
||||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
|
||||||
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
EIGEN_STATIC_ASSERT_LVALUE(DstXprType)
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(DstXprType,SrcXprType)
|
||||||
|
EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||||
|
|
||||||
typedef swap_kernel<DstEvaluatorType,SrcEvaluatorType> Kernel;
|
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||||
Kernel kernel(dstEvaluator, srcEvaluator, dst.const_cast_derived());
|
|
||||||
|
#ifdef EIGEN_DEBUG_ASSIGN
|
||||||
dense_assignment_loop<Kernel>::run(kernel);
|
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
|
||||||
}
|
#endif
|
||||||
|
|
||||||
// Based on MatrixBase::operator+= (in CwiseBinaryOp.h)
|
call_dense_assignment_loop(dst, src, func);
|
||||||
template<typename DstXprType, typename SrcXprType>
|
}
|
||||||
void add_assign_using_evaluator(const MatrixBase<DstXprType>& dst, const MatrixBase<SrcXprType>& src)
|
};
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), add_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on ArrayBase::operator+=
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void add_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), add_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Add add_assign_using_evaluator for EigenBase ? (Jitse)
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void subtract_assign_using_evaluator(const MatrixBase<DstXprType>& dst, const MatrixBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), sub_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void subtract_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), sub_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void multiply_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), mul_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void divide_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
copy_using_evaluator(dst.derived(), src.derived(), div_assign_op<Scalar>());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -30,8 +30,9 @@ namespace Eigen {
|
|||||||
template<typename ExpressionType, template <typename> class StorageBase>
|
template<typename ExpressionType, template <typename> class StorageBase>
|
||||||
class NoAlias
|
class NoAlias
|
||||||
{
|
{
|
||||||
typedef typename ExpressionType::Scalar Scalar;
|
|
||||||
public:
|
public:
|
||||||
|
typedef typename ExpressionType::Scalar Scalar;
|
||||||
|
|
||||||
NoAlias(ExpressionType& expression) : m_expression(expression) {}
|
NoAlias(ExpressionType& expression) : m_expression(expression) {}
|
||||||
|
|
||||||
/** Behaves like MatrixBase::lazyAssign(other)
|
/** Behaves like MatrixBase::lazyAssign(other)
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
|
// #ifndef EIGEN_TEST_EVALUATORS
|
||||||
|
|
||||||
/** \class SwapWrapper
|
/** \class SwapWrapper
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
*
|
*
|
||||||
@ -135,6 +137,76 @@ template<typename ExpressionType> class SwapWrapper
|
|||||||
ExpressionType& m_expression;
|
ExpressionType& m_expression;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Overload default assignPacket behavior for swapping them
|
||||||
|
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT>
|
||||||
|
class dense_swap_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> >
|
||||||
|
{
|
||||||
|
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> > Base;
|
||||||
|
typedef typename DstEvaluatorTypeT::PacketScalar PacketScalar;
|
||||||
|
using Base::m_dst;
|
||||||
|
using Base::m_src;
|
||||||
|
using Base::m_functor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Base::Scalar Scalar;
|
||||||
|
typedef typename Base::Index Index;
|
||||||
|
typedef typename Base::DstXprType DstXprType;
|
||||||
|
|
||||||
|
dense_swap_kernel(DstEvaluatorTypeT &dst, const SrcEvaluatorTypeT &src, DstXprType& dstExpr)
|
||||||
|
: Base(dst, src, swap_assign_op<Scalar>(), dstExpr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<int StoreMode, int LoadMode>
|
||||||
|
void assignPacket(Index row, Index col)
|
||||||
|
{
|
||||||
|
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(row,col), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(row,col));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int StoreMode, int LoadMode>
|
||||||
|
void assignPacket(Index index)
|
||||||
|
{
|
||||||
|
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(index), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I mean no CRTP (Gael)
|
||||||
|
template<int StoreMode, int LoadMode>
|
||||||
|
void assignPacketByOuterInner(Index outer, Index inner)
|
||||||
|
{
|
||||||
|
Index row = Base::rowIndexByOuterInner(outer, inner);
|
||||||
|
Index col = Base::colIndexByOuterInner(outer, inner);
|
||||||
|
assignPacket<StoreMode,LoadMode>(row, col);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void call_dense_swap_loop(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
// TODO there is too much redundancy with call_dense_assignment_loop
|
||||||
|
|
||||||
|
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||||
|
|
||||||
|
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
||||||
|
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
||||||
|
|
||||||
|
DstEvaluatorType dstEvaluator(dst);
|
||||||
|
SrcEvaluatorType srcEvaluator(src);
|
||||||
|
|
||||||
|
typedef dense_swap_kernel<DstEvaluatorType,SrcEvaluatorType> Kernel;
|
||||||
|
Kernel kernel(dstEvaluator, srcEvaluator, dst.const_cast_derived());
|
||||||
|
|
||||||
|
dense_assignment_loop<Kernel>::run(kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_SWAP_H
|
#endif // EIGEN_SWAP_H
|
||||||
|
@ -293,6 +293,15 @@ struct transfer_constness
|
|||||||
>::type type;
|
>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
|
||||||
|
// When using evaluators, we never evaluate when assembling the expression!!
|
||||||
|
template<typename T, int n=1, typename PlainObject = typename eval<T>::type> struct nested
|
||||||
|
{
|
||||||
|
typedef typename ref_selector<T>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
/** \internal Determines how a given expression should be nested into another one.
|
/** \internal Determines how a given expression should be nested into another one.
|
||||||
* For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
|
* For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
|
||||||
* nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
|
* nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
|
||||||
@ -339,6 +348,7 @@ template<typename T, int n=1, typename PlainObject = typename eval<T>::type> str
|
|||||||
typename ref_selector<T>::type
|
typename ref_selector<T>::type
|
||||||
>::type type;
|
>::type type;
|
||||||
};
|
};
|
||||||
|
#endif // EIGEN_TEST_EVALUATORS
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
|
@ -1,7 +1,81 @@
|
|||||||
|
|
||||||
|
#ifndef EIGEN_ENABLE_EVALUATORS
|
||||||
#define EIGEN_ENABLE_EVALUATORS
|
#define EIGEN_ENABLE_EVALUATORS
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
using internal::copy_using_evaluator;
|
namespace Eigen {
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
EIGEN_STRONG_INLINE
|
||||||
|
DstXprType& copy_using_evaluator(const EigenBase<DstXprType> &dst, const SrcXprType &src)
|
||||||
|
{
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar>());
|
||||||
|
return dst.const_cast_derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, template <typename> class StorageBase, typename SrcXprType>
|
||||||
|
EIGEN_STRONG_INLINE
|
||||||
|
const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& dst, const SrcXprType &src)
|
||||||
|
{
|
||||||
|
call_assignment(dst, src.derived(), internal::assign_op<typename DstXprType::Scalar>());
|
||||||
|
return dst.expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
EIGEN_STRONG_INLINE
|
||||||
|
DstXprType& copy_using_evaluator(const PlainObjectBase<DstXprType> &dst, const SrcXprType &src)
|
||||||
|
{
|
||||||
|
#ifdef EIGEN_NO_AUTOMATIC_RESIZING
|
||||||
|
eigen_assert((dst.size()==0 || (IsVectorAtCompileTime ? (dst.size() == src.size())
|
||||||
|
: (dst.rows() == src.rows() && dst.cols() == src.cols())))
|
||||||
|
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
|
||||||
|
#else
|
||||||
|
dst.const_cast_derived().resizeLike(src.derived());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar>());
|
||||||
|
return dst.const_cast_derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void add_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
typedef typename DstXprType::Scalar Scalar;
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::add_assign_op<Scalar>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void subtract_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
typedef typename DstXprType::Scalar Scalar;
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::sub_assign_op<Scalar>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void multiply_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
typedef typename DstXprType::Scalar Scalar;
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::mul_assign_op<Scalar>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void divide_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
typedef typename DstXprType::Scalar Scalar;
|
||||||
|
call_assignment(dst.const_cast_derived(), src.derived(), internal::div_assign_op<Scalar>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstXprType, typename SrcXprType>
|
||||||
|
void swap_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
||||||
|
{
|
||||||
|
call_dense_swap_loop(dst.const_cast_derived(), src.const_cast_derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define VERIFY_IS_APPROX_EVALUATOR(DEST,EXPR) VERIFY_IS_APPROX(copy_using_evaluator(DEST,(EXPR)), (EXPR).eval());
|
#define VERIFY_IS_APPROX_EVALUATOR(DEST,EXPR) VERIFY_IS_APPROX(copy_using_evaluator(DEST,(EXPR)), (EXPR).eval());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user