CwiseBinaryOp.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
  6. //
  7. // This Source Code Form is subject to the terms of the Mozilla
  8. // Public License v. 2.0. If a copy of the MPL was not distributed
  9. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  10. #ifndef EIGEN_CWISE_BINARY_OP_H
  11. #define EIGEN_CWISE_BINARY_OP_H
  12. namespace Eigen {
  13. namespace internal {
  14. template<typename BinaryOp, typename Lhs, typename Rhs>
  15. struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
  16. {
  17. // we must not inherit from traits<Lhs> since it has
  18. // the potential to cause problems with MSVC
  19. typedef typename remove_all<Lhs>::type Ancestor;
  20. typedef typename traits<Ancestor>::XprKind XprKind;
  21. enum {
  22. RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
  23. ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
  24. MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
  25. MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
  26. };
  27. // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor),
  28. // we still want to handle the case when the result type is different.
  29. typedef typename result_of<
  30. BinaryOp(
  31. const typename Lhs::Scalar&,
  32. const typename Rhs::Scalar&
  33. )
  34. >::type Scalar;
  35. typedef typename cwise_promote_storage_type<typename traits<Lhs>::StorageKind,
  36. typename traits<Rhs>::StorageKind,
  37. BinaryOp>::ret StorageKind;
  38. typedef typename promote_index_type<typename traits<Lhs>::StorageIndex,
  39. typename traits<Rhs>::StorageIndex>::type StorageIndex;
  40. typedef typename Lhs::Nested LhsNested;
  41. typedef typename Rhs::Nested RhsNested;
  42. typedef typename remove_reference<LhsNested>::type _LhsNested;
  43. typedef typename remove_reference<RhsNested>::type _RhsNested;
  44. enum {
  45. Flags = cwise_promote_storage_order<typename traits<Lhs>::StorageKind,typename traits<Rhs>::StorageKind,_LhsNested::Flags & RowMajorBit,_RhsNested::Flags & RowMajorBit>::value
  46. };
  47. };
  48. } // end namespace internal
  49. template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
  50. class CwiseBinaryOpImpl;
  51. /** \class CwiseBinaryOp
  52. * \ingroup Core_Module
  53. *
  54. * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions
  55. *
  56. * \tparam BinaryOp template functor implementing the operator
  57. * \tparam LhsType the type of the left-hand side
  58. * \tparam RhsType the type of the right-hand side
  59. *
  60. * This class represents an expression where a coefficient-wise binary operator is applied to two expressions.
  61. * It is the return type of binary operators, by which we mean only those binary operators where
  62. * both the left-hand side and the right-hand side are Eigen expressions.
  63. * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp.
  64. *
  65. * Most of the time, this is the only way that it is used, so you typically don't have to name
  66. * CwiseBinaryOp types explicitly.
  67. *
  68. * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp
  69. */
  70. template<typename BinaryOp, typename LhsType, typename RhsType>
  71. class CwiseBinaryOp :
  72. public CwiseBinaryOpImpl<
  73. BinaryOp, LhsType, RhsType,
  74. typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind,
  75. typename internal::traits<RhsType>::StorageKind,
  76. BinaryOp>::ret>,
  77. internal::no_assignment_operator
  78. {
  79. public:
  80. typedef typename internal::remove_all<BinaryOp>::type Functor;
  81. typedef typename internal::remove_all<LhsType>::type Lhs;
  82. typedef typename internal::remove_all<RhsType>::type Rhs;
  83. typedef typename CwiseBinaryOpImpl<
  84. BinaryOp, LhsType, RhsType,
  85. typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind,
  86. typename internal::traits<Rhs>::StorageKind,
  87. BinaryOp>::ret>::Base Base;
  88. EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
  89. typedef typename internal::ref_selector<LhsType>::type LhsNested;
  90. typedef typename internal::ref_selector<RhsType>::type RhsNested;
  91. typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
  92. typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
  93. #if EIGEN_COMP_MSVC && EIGEN_HAS_CXX11
  94. //Required for Visual Studio or the Copy constructor will probably not get inlined!
  95. EIGEN_STRONG_INLINE
  96. CwiseBinaryOp(const CwiseBinaryOp<BinaryOp,LhsType,RhsType>&) = default;
  97. #endif
  98. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  99. CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp())
  100. : m_lhs(aLhs), m_rhs(aRhs), m_functor(func)
  101. {
  102. EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
  103. // require the sizes to match
  104. EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
  105. eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols());
  106. }
  107. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
  108. Index rows() const EIGEN_NOEXCEPT {
  109. // return the fixed size type if available to enable compile time optimizations
  110. return internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic ? m_rhs.rows() : m_lhs.rows();
  111. }
  112. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
  113. Index cols() const EIGEN_NOEXCEPT {
  114. // return the fixed size type if available to enable compile time optimizations
  115. return internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic ? m_rhs.cols() : m_lhs.cols();
  116. }
  117. /** \returns the left hand side nested expression */
  118. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  119. const _LhsNested& lhs() const { return m_lhs; }
  120. /** \returns the right hand side nested expression */
  121. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  122. const _RhsNested& rhs() const { return m_rhs; }
  123. /** \returns the functor representing the binary operation */
  124. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  125. const BinaryOp& functor() const { return m_functor; }
  126. protected:
  127. LhsNested m_lhs;
  128. RhsNested m_rhs;
  129. const BinaryOp m_functor;
  130. };
  131. // Generic API dispatcher
  132. template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
  133. class CwiseBinaryOpImpl
  134. : public internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
  135. {
  136. public:
  137. typedef typename internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
  138. };
  139. /** replaces \c *this by \c *this - \a other.
  140. *
  141. * \returns a reference to \c *this
  142. */
  143. template<typename Derived>
  144. template<typename OtherDerived>
  145. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
  146. MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
  147. {
  148. call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
  149. return derived();
  150. }
  151. /** replaces \c *this by \c *this + \a other.
  152. *
  153. * \returns a reference to \c *this
  154. */
  155. template<typename Derived>
  156. template<typename OtherDerived>
  157. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
  158. MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
  159. {
  160. call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
  161. return derived();
  162. }
  163. } // end namespace Eigen
  164. #endif // EIGEN_CWISE_BINARY_OP_H