// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2019 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARTIAL_REDUX_H #define EIGEN_PARTIAL_REDUX_H // IWYU pragma: private #include "./InternalHeaderCheck.h" namespace Eigen { /** \class PartialReduxExpr * \ingroup Core_Module * * \brief Generic expression of a partially reduxed matrix * * \tparam MatrixType the type of the matrix we are applying the redux operation * \tparam MemberOp type of the member functor * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal) * * This class represents an expression of a partial redux operator of a matrix. * It is the return type of some VectorwiseOp functions, * and most of the time this is the only way it is used. * * \sa class VectorwiseOp */ template class PartialReduxExpr; namespace internal { template struct traits > : traits { typedef typename MemberOp::result_type Scalar; typedef typename traits::StorageKind StorageKind; typedef typename traits::XprKind XprKind; typedef typename MatrixType::Scalar InputScalar; enum { RowsAtCompileTime = Direction == Vertical ? 1 : MatrixType::RowsAtCompileTime, ColsAtCompileTime = Direction == Horizontal ? 1 : MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = Direction == Vertical ? 1 : MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = Direction == Horizontal ? 1 : MatrixType::MaxColsAtCompileTime, Flags = RowsAtCompileTime == 1 ? RowMajorBit : 0, TraversalSize = Direction == Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime }; }; } // namespace internal template class PartialReduxExpr : public internal::dense_xpr_base >::type, internal::no_assignment_operator { public: typedef typename internal::dense_xpr_base::type Base; EIGEN_DENSE_PUBLIC_INTERFACE(PartialReduxExpr) EIGEN_DEVICE_FUNC explicit PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp()) : m_matrix(mat), m_functor(func) {} EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return (Direction == Vertical ? 1 : m_matrix.rows()); } EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return (Direction == Horizontal ? 1 : m_matrix.cols()); } EIGEN_DEVICE_FUNC typename MatrixType::Nested nestedExpression() const { return m_matrix; } EIGEN_DEVICE_FUNC const MemberOp& functor() const { return m_functor; } protected: typename MatrixType::Nested m_matrix; const MemberOp m_functor; }; template struct partial_redux_dummy_func; #define EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(MEMBER, COST, VECTORIZABLE, BINARYOP) \ template \ struct member_##MEMBER { \ typedef ResultType result_type; \ typedef BINARYOP BinaryOp; \ template \ struct Cost { \ enum { value = COST }; \ }; \ enum { Vectorizable = VECTORIZABLE }; \ template \ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const { \ return mat.MEMBER(); \ } \ BinaryOp binaryFunc() const { return BinaryOp(); } \ } #define EIGEN_MEMBER_FUNCTOR(MEMBER, COST) EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(MEMBER, COST, 0, partial_redux_dummy_func) namespace internal { EIGEN_MEMBER_FUNCTOR(norm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); EIGEN_MEMBER_FUNCTOR(stableNorm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); EIGEN_MEMBER_FUNCTOR(blueNorm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size - 1) * functor_traits >::Cost); EIGEN_MEMBER_FUNCTOR(all, (Size - 1) * NumTraits::AddCost); EIGEN_MEMBER_FUNCTOR(any, (Size - 1) * NumTraits::AddCost); EIGEN_MEMBER_FUNCTOR(count, (Size - 1) * NumTraits::AddCost); EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(sum, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_sum_op); EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(minCoeff, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_min_op); EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(maxCoeff, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_max_op); EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(prod, (Size - 1) * NumTraits::MulCost, 1, internal::scalar_product_op); template struct member_lpnorm { typedef ResultType result_type; enum { Vectorizable = 0 }; template struct Cost { enum { value = (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost }; }; EIGEN_DEVICE_FUNC member_lpnorm() {} template EIGEN_DEVICE_FUNC inline ResultType operator()(const XprType& mat) const { return mat.template lpNorm

(); } }; template struct member_redux { typedef BinaryOpT BinaryOp; typedef typename result_of::type result_type; enum { Vectorizable = functor_traits::PacketAccess }; template struct Cost { enum { value = (Size - 1) * functor_traits::Cost }; }; EIGEN_DEVICE_FUNC explicit member_redux(const BinaryOp func) : m_functor(func) {} template EIGEN_DEVICE_FUNC inline result_type operator()(const DenseBase& mat) const { return mat.redux(m_functor); } const BinaryOp& binaryFunc() const { return m_functor; } const BinaryOp m_functor; }; } // namespace internal /** \class VectorwiseOp * \ingroup Core_Module * * \brief Pseudo expression providing broadcasting and partial reduction operations * * \tparam ExpressionType the type of the object on which to do partial reductions * \tparam Direction indicates whether to operate on columns (#Vertical) or rows (#Horizontal) * * This class represents a pseudo expression with broadcasting and partial reduction features. * It is the return type of DenseBase::colwise() and DenseBase::rowwise() * and most of the time this is the only way it is explicitly used. * * To understand the logic of rowwise/colwise expression, let's consider a generic case `A.colwise().foo()` * where `foo` is any method of `VectorwiseOp`. This expression is equivalent to applying `foo()` to each * column of `A` and then re-assemble the outputs in a matrix expression: * \code [A.col(0).foo(), A.col(1).foo(), ..., A.col(A.cols()-1).foo()] \endcode * * Example: \include MatrixBase_colwise.cpp * Output: \verbinclude MatrixBase_colwise.out * * The begin() and end() methods are obviously exceptions to the previous rule as they * return STL-compatible begin/end iterators to the rows or columns of the nested expression. * Typical use cases include for-range-loop and calls to STL algorithms: * * Example: \include MatrixBase_colwise_iterator_cxx11.cpp * Output: \verbinclude MatrixBase_colwise_iterator_cxx11.out * * For a partial reduction on an empty input, some rules apply. * For the sake of clarity, let's consider a vertical reduction: * - If the number of columns is zero, then a 1x0 row-major vector expression is returned. * - Otherwise, if the number of rows is zero, then * - a row vector of zeros is returned for sum-like reductions (sum, squaredNorm, norm, etc.) * - a row vector of ones is returned for a product reduction (e.g., MatrixXd(n,0).colwise().prod()) * - an assert is triggered for all other reductions (minCoeff,maxCoeff,redux(bin_op)) * * \sa DenseBase::colwise(), DenseBase::rowwise(), class PartialReduxExpr */ template class VectorwiseOp { public: typedef typename ExpressionType::Scalar Scalar; typedef typename ExpressionType::RealScalar RealScalar; typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 typedef typename internal::ref_selector::non_const_type ExpressionTypeNested; typedef internal::remove_all_t ExpressionTypeNestedCleaned; template