diff options
author | Jitse Niesen <jitse@maths.leeds.ac.uk> | 2011-03-27 22:08:48 +0100 |
---|---|---|
committer | Jitse Niesen <jitse@maths.leeds.ac.uk> | 2011-03-27 22:08:48 +0100 |
commit | b175bc464fc1ac554832510d0614194e8c406a09 (patch) | |
tree | ae293c4354f9e47fdf8952fc314b1eed7ff7bdd8 | |
parent | 1b17a674dd409ea55cea4079ba9b8db18778e012 (diff) |
Evaluators: Implement linear traversal, better testing.
-rw-r--r-- | Eigen/src/Core/AssignEvaluator.h | 29 | ||||
-rw-r--r-- | Eigen/src/Core/CoreEvaluators.h | 65 | ||||
-rw-r--r-- | test/evaluators.cpp | 36 |
3 files changed, 122 insertions, 8 deletions
diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 2d61e7ff6..0b90ef70f 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -78,8 +78,8 @@ public: enum { Traversal = int(MayInnerVectorize) ? int(InnerVectorizedTraversal) : int(MayLinearVectorize) ? int(LinearVectorizedTraversal) - : int(MaySliceVectorize) ? int(DefaultTraversal) // int(SliceVectorizedTraversal) - : int(MayLinearize) ? int(DefaultTraversal) // int(LinearTraversal) + : int(MaySliceVectorize) ? int(SliceVectorizedTraversal) + : int(MayLinearize) ? int(LinearTraversal) : int(DefaultTraversal), Vectorized = int(Traversal) == InnerVectorizedTraversal || int(Traversal) == LinearVectorizedTraversal @@ -264,12 +264,37 @@ struct copy_using_evaluator_impl<DstXprType, SrcXprType, InnerVectorizedTraversa } }; +/*********************** +*** Linear traversal *** +***********************/ + +template<typename DstXprType, typename SrcXprType> +struct copy_using_evaluator_impl<DstXprType, SrcXprType, LinearTraversal, NoUnrolling> +{ + inline static void run(const DstXprType &dst, const SrcXprType &src) + { + typedef typename evaluator<DstXprType>::type DstEvaluatorType; + typedef typename evaluator<SrcXprType>::type SrcEvaluatorType; + typedef typename DstXprType::Index Index; + + DstEvaluatorType dstEvaluator(dst.const_cast_derived()); + SrcEvaluatorType srcEvaluator(src); + + const Index size = dst.size(); + for(Index i = 0; i < size; ++i) + dstEvaluator.coeffRef(i) = srcEvaluator.coeff(i); // TODO: use copyCoeff ? + } +}; + // Based on DenseBase::LazyAssign() template<typename DstXprType, typename SrcXprType> const DstXprType& copy_using_evaluator(const DstXprType& dst, const SrcXprType& src) { +#ifdef EIGEN_DEBUG_ASSIGN + internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug(); +#endif copy_using_evaluator_impl<DstXprType, SrcXprType>::run(dst, src); return dst; } diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index c06d9303e..734936681 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -60,11 +60,21 @@ struct evaluator_impl<Transpose<ExpressionType> > return m_argImpl.coeff(j, i); } + typename TransposeType::CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(index); + } + typename TransposeType::Scalar& coeffRef(Index i, Index j) { return m_argImpl.coeffRef(j, i); } + typename TransposeType::Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(index); + } + template<int LoadMode> const typename ExpressionType::PacketScalar packet(Index index) const { @@ -79,12 +89,11 @@ struct evaluator_impl<Transpose<ExpressionType> > return m_argImpl.template packetByOuterInner<LoadMode>(outer, inner); } -// TODO: Is this function needed? -// template<int StoreMode> -// void writePacket(Index index, const typename ExpressionType::PacketScalar& x) -// { -// m_argImpl.template writePacket<StoreMode>(index, x); -// } + template<int StoreMode> + void writePacket(Index index, const typename ExpressionType::PacketScalar& x) + { + m_argImpl.template writePacket<StoreMode>(index, x); + } template<int StoreMode> void writePacketByOuterInner(Index outer, Index inner, const typename ExpressionType::PacketScalar& x) @@ -122,11 +131,21 @@ struct evaluator_impl<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > return m_matrix.coeff(i, j); } + typename MatrixType::CoeffReturnType coeff(Index index) const + { + return m_matrix.coeff(index); + } + typename MatrixType::Scalar& coeffRef(Index i, Index j) { return m_matrix.const_cast_derived().coeffRef(i, j); } + typename MatrixType::Scalar& coeffRef(Index index) + { + return m_matrix.const_cast_derived().coeffRef(index); + } + template<int LoadMode> typename MatrixType::PacketReturnType packet(Index index) const { @@ -191,6 +210,11 @@ struct evaluator_impl<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > return m_array.const_cast_derived().coeffRef(i, j); } + typename ArrayType::Scalar& coeffRef(Index index) + { + return m_array.const_cast_derived().coeffRef(index); + } + template<int LoadMode> typename ArrayType::PacketReturnType packet(Index index) const { @@ -243,6 +267,11 @@ struct evaluator_impl<CwiseNullaryOp<NullaryOp,PlainObjectType> > return m_nullaryOp.coeff(i, j); } + typename NullaryOpType::CoeffReturnType coeff(Index index) const + { + return m_nullaryOp.coeff(index); + } + template<int LoadMode> typename NullaryOpType::PacketScalar packet(Index index) const { @@ -269,6 +298,11 @@ struct evaluator_impl<CwiseUnaryOp<UnaryOp, ArgType> > return m_unaryOp.functor()(m_argImpl.coeff(i, j)); } + typename UnaryOpType::CoeffReturnType coeff(Index index) const + { + return m_unaryOp.functor()(m_argImpl.coeff(index)); + } + template<int LoadMode> typename UnaryOpType::PacketScalar packet(Index index) const { @@ -309,6 +343,11 @@ struct evaluator_impl<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > return m_binaryOp.functor()(m_lhsImpl.coeff(i, j), m_rhsImpl.coeff(i, j)); } + typename BinaryOpType::CoeffReturnType coeff(Index index) const + { + return m_binaryOp.functor()(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index)); + } + template<int LoadMode> typename BinaryOpType::PacketScalar packet(Index index) const { @@ -316,6 +355,20 @@ struct evaluator_impl<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > m_rhsImpl.template packet<LoadMode>(index)); } + template<int LoadMode> + typename BinaryOpType::PacketScalar packet(Index row, Index col) const + { + return m_binaryOp.functor().packetOp(m_lhsImpl.template packet<LoadMode>(row, col), + m_rhsImpl.template packet<LoadMode>(row, col)); + } + + template<int LoadMode> + typename BinaryOpType::PacketScalar packetByOuterInner(Index outer, Index inner) const + { + return packet<LoadMode>(m_lhsImpl.rowIndexByOuterInner(outer, inner), + m_lhsImpl.colIndexByOuterInner(outer, inner)); + } + protected: const BinaryOpType& m_binaryOp; typename evaluator<Lhs>::type m_lhsImpl; diff --git a/test/evaluators.cpp b/test/evaluators.cpp index 0e703360b..b804171a7 100644 --- a/test/evaluators.cpp +++ b/test/evaluators.cpp @@ -89,4 +89,40 @@ void test_evaluators() ArrayXXd arr1(6,6), arr2(6,6); VERIFY_IS_APPROX_EVALUATOR(arr1, ArrayXXd::Constant(6,6, 3.0)); VERIFY_IS_APPROX_EVALUATOR(arr2, arr1); + + // test direct traversal + Matrix3f m3; + Array33f a3; + VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Identity()); // matrix, nullary + // TODO: find a way to test direct traversal with array + VERIFY_IS_APPROX_EVALUATOR(m3.transpose(), Matrix3f::Identity().transpose()); // transpose + VERIFY_IS_APPROX_EVALUATOR(m3, 2 * Matrix3f::Identity()); // unary + VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Identity() + m3); // binary + + // test linear traversal + VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Zero()); // matrix, nullary + VERIFY_IS_APPROX_EVALUATOR(a3, Array33f::Zero()); // array + VERIFY_IS_APPROX_EVALUATOR(m3.transpose(), Matrix3f::Zero().transpose()); // transpose + VERIFY_IS_APPROX_EVALUATOR(m3, 2 * Matrix3f::Zero()); // unary + VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Zero() + m3); // binary + + // test inner vectorization + Matrix4f m4, m4src = Matrix4f::Random(); + Array44f a4, a4src = Matrix4f::Random(); + VERIFY_IS_APPROX_EVALUATOR(m4, m4src); // matrix + VERIFY_IS_APPROX_EVALUATOR(a4, a4src); // array + VERIFY_IS_APPROX_EVALUATOR(m4.transpose(), m4src.transpose()); // transpose + // TODO: find out why Matrix4f::Zero() does not allow inner vectorization + VERIFY_IS_APPROX_EVALUATOR(m4, 2 * m4src); // unary + VERIFY_IS_APPROX_EVALUATOR(m4, m4src + m4src); // binary + + // test linear vectorization + MatrixXf mX(6,6), mXsrc = MatrixXf::Random(6,6); + ArrayXXf aX(6,6), aXsrc = MatrixXf::Random(6,6); + VERIFY_IS_APPROX_EVALUATOR(mX, mXsrc); // matrix + VERIFY_IS_APPROX_EVALUATOR(aX, aXsrc); // array + VERIFY_IS_APPROX_EVALUATOR(mX.transpose(), mXsrc.transpose()); // transpose + VERIFY_IS_APPROX_EVALUATOR(mX, MatrixXf::Zero(6,6)); // nullary + VERIFY_IS_APPROX_EVALUATOR(mX, 2 * mXsrc); // unary + VERIFY_IS_APPROX_EVALUATOR(mX, mXsrc + mXsrc); // binary } |