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 11 #ifndef EIGEN_CWISE_BINARY_OP_H 12 #define EIGEN_CWISE_BINARY_OP_H 13 14 namespace Eigen { 15 16 namespace internal { 17 template<typename BinaryOp, typename Lhs, typename Rhs> 18 struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 19 { 20 // we must not inherit from traits<Lhs> since it has 21 // the potential to cause problems with MSVC 22 typedef typename remove_all<Lhs>::type Ancestor; 23 typedef typename traits<Ancestor>::XprKind XprKind; 24 enum { 25 RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime, 26 ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime, 27 MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime, 28 MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime 29 }; 30 31 // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor), 32 // we still want to handle the case when the result type is different. 33 typedef typename result_of< 34 BinaryOp( 35 const typename Lhs::Scalar&, 36 const typename Rhs::Scalar& 37 ) 38 >::type Scalar; 39 typedef typename cwise_promote_storage_type<typename traits<Lhs>::StorageKind, 40 typename traits<Rhs>::StorageKind, 41 BinaryOp>::ret StorageKind; 42 typedef typename promote_index_type<typename traits<Lhs>::StorageIndex, 43 typename traits<Rhs>::StorageIndex>::type StorageIndex; 44 typedef typename Lhs::Nested LhsNested; 45 typedef typename Rhs::Nested RhsNested; 46 typedef typename remove_reference<LhsNested>::type _LhsNested; 47 typedef typename remove_reference<RhsNested>::type _RhsNested; 48 enum { 49 Flags = cwise_promote_storage_order<typename traits<Lhs>::StorageKind,typename traits<Rhs>::StorageKind,_LhsNested::Flags & RowMajorBit,_RhsNested::Flags & RowMajorBit>::value 50 }; 51 }; 52 } // end namespace internal 53 54 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind> 55 class CwiseBinaryOpImpl; 56 57 /** \class CwiseBinaryOp 58 * \ingroup Core_Module 59 * 60 * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions 61 * 62 * \tparam BinaryOp template functor implementing the operator 63 * \tparam LhsType the type of the left-hand side 64 * \tparam RhsType the type of the right-hand side 65 * 66 * This class represents an expression where a coefficient-wise binary operator is applied to two expressions. 67 * It is the return type of binary operators, by which we mean only those binary operators where 68 * both the left-hand side and the right-hand side are Eigen expressions. 69 * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp. 70 * 71 * Most of the time, this is the only way that it is used, so you typically don't have to name 72 * CwiseBinaryOp types explicitly. 73 * 74 * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp 75 */ 76 template<typename BinaryOp, typename LhsType, typename RhsType> 77 class CwiseBinaryOp : 78 public CwiseBinaryOpImpl< 79 BinaryOp, LhsType, RhsType, 80 typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind, 81 typename internal::traits<RhsType>::StorageKind, 82 BinaryOp>::ret>, 83 internal::no_assignment_operator 84 { 85 public: 86 87 typedef typename internal::remove_all<BinaryOp>::type Functor; 88 typedef typename internal::remove_all<LhsType>::type Lhs; 89 typedef typename internal::remove_all<RhsType>::type Rhs; 90 91 typedef typename CwiseBinaryOpImpl< 92 BinaryOp, LhsType, RhsType, 93 typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind, 94 typename internal::traits<Rhs>::StorageKind, 95 BinaryOp>::ret>::Base Base; 96 EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp) 97 98 typedef typename internal::ref_selector<LhsType>::type LhsNested; 99 typedef typename internal::ref_selector<RhsType>::type RhsNested; 100 typedef typename internal::remove_reference<LhsNested>::type _LhsNested; 101 typedef typename internal::remove_reference<RhsNested>::type _RhsNested; 102 103 EIGEN_DEVICE_FUNC 104 EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp()) 105 : m_lhs(aLhs), m_rhs(aRhs), m_functor(func) 106 { 107 EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar); 108 // require the sizes to match 109 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) 110 eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()); 111 } 112 113 EIGEN_DEVICE_FUNC 114 EIGEN_STRONG_INLINE Index rows() const { 115 // return the fixed size type if available to enable compile time optimizations 116 if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic) 117 return m_rhs.rows(); 118 else 119 return m_lhs.rows(); 120 } 121 EIGEN_DEVICE_FUNC 122 EIGEN_STRONG_INLINE Index cols() const { 123 // return the fixed size type if available to enable compile time optimizations 124 if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic) 125 return m_rhs.cols(); 126 else 127 return m_lhs.cols(); 128 } 129 130 /** \returns the left hand side nested expression */ 131 EIGEN_DEVICE_FUNC 132 const _LhsNested& lhs() const { return m_lhs; } 133 /** \returns the right hand side nested expression */ 134 EIGEN_DEVICE_FUNC 135 const _RhsNested& rhs() const { return m_rhs; } 136 /** \returns the functor representing the binary operation */ 137 EIGEN_DEVICE_FUNC 138 const BinaryOp& functor() const { return m_functor; } 139 140 protected: 141 LhsNested m_lhs; 142 RhsNested m_rhs; 143 const BinaryOp m_functor; 144 }; 145 146 // Generic API dispatcher 147 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind> 148 class CwiseBinaryOpImpl 149 : public internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type 150 { 151 public: 152 typedef typename internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base; 153 }; 154 155 /** replaces \c *this by \c *this - \a other. 156 * 157 * \returns a reference to \c *this 158 */ 159 template<typename Derived> 160 template<typename OtherDerived> 161 EIGEN_STRONG_INLINE Derived & 162 MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other) 163 { 164 call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>()); 165 return derived(); 166 } 167 168 /** replaces \c *this by \c *this + \a other. 169 * 170 * \returns a reference to \c *this 171 */ 172 template<typename Derived> 173 template<typename OtherDerived> 174 EIGEN_STRONG_INLINE Derived & 175 MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other) 176 { 177 call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>()); 178 return derived(); 179 } 180 181 } // end namespace Eigen 182 183 #endif // EIGEN_CWISE_BINARY_OP_H 184 185