Eigne Matrix Class Library
Dependents: Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more
CwiseBinaryOp.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_CWISE_BINARY_OP_H 00012 #define EIGEN_CWISE_BINARY_OP_H 00013 00014 namespace Eigen { 00015 00016 /** \class CwiseBinaryOp 00017 * \ingroup Core_Module 00018 * 00019 * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions 00020 * 00021 * \param BinaryOp template functor implementing the operator 00022 * \param Lhs the type of the left-hand side 00023 * \param Rhs the type of the right-hand side 00024 * 00025 * This class represents an expression where a coefficient-wise binary operator is applied to two expressions. 00026 * It is the return type of binary operators, by which we mean only those binary operators where 00027 * both the left-hand side and the right-hand side are Eigen expressions. 00028 * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp. 00029 * 00030 * Most of the time, this is the only way that it is used, so you typically don't have to name 00031 * CwiseBinaryOp types explicitly. 00032 * 00033 * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp 00034 */ 00035 00036 namespace internal { 00037 template<typename BinaryOp, typename Lhs, typename Rhs> 00038 struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 00039 { 00040 // we must not inherit from traits<Lhs> since it has 00041 // the potential to cause problems with MSVC 00042 typedef typename remove_all<Lhs>::type Ancestor; 00043 typedef typename traits<Ancestor>::XprKind XprKind; 00044 enum { 00045 RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime, 00046 ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime, 00047 MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime, 00048 MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime 00049 }; 00050 00051 // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor), 00052 // we still want to handle the case when the result type is different. 00053 typedef typename result_of< 00054 BinaryOp( 00055 typename Lhs::Scalar, 00056 typename Rhs::Scalar 00057 ) 00058 >::type Scalar; 00059 typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, 00060 typename traits<Rhs>::StorageKind>::ret StorageKind; 00061 typedef typename promote_index_type<typename traits<Lhs>::Index, 00062 typename traits<Rhs>::Index>::type Index; 00063 typedef typename Lhs::Nested LhsNested; 00064 typedef typename Rhs::Nested RhsNested; 00065 typedef typename remove_reference<LhsNested>::type _LhsNested; 00066 typedef typename remove_reference<RhsNested>::type _RhsNested; 00067 enum { 00068 LhsCoeffReadCost = _LhsNested::CoeffReadCost, 00069 RhsCoeffReadCost = _RhsNested::CoeffReadCost, 00070 LhsFlags = _LhsNested::Flags, 00071 RhsFlags = _RhsNested::Flags, 00072 SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value, 00073 StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit), 00074 Flags0 = (int(LhsFlags) | int(RhsFlags)) & ( 00075 HereditaryBits 00076 | (int(LhsFlags) & int(RhsFlags) & 00077 ( AlignedBit 00078 | (StorageOrdersAgree ? LinearAccessBit : 0) 00079 | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0) 00080 ) 00081 ) 00082 ), 00083 Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit), 00084 Cost0 = EIGEN_ADD_COST(LhsCoeffReadCost,RhsCoeffReadCost), 00085 CoeffReadCost = EIGEN_ADD_COST(Cost0,functor_traits<BinaryOp>::Cost) 00086 }; 00087 }; 00088 } // end namespace internal 00089 00090 // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor 00091 // that would take two operands of different types. If there were such an example, then this check should be 00092 // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as 00093 // currently they take only one typename Scalar template parameter. 00094 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. 00095 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to 00096 // add together a float matrix and a double matrix. 00097 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ 00098 EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \ 00099 ? int(internal::scalar_product_traits<LHS, RHS>::Defined) \ 00100 : int(internal::is_same<LHS, RHS>::value)), \ 00101 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 00102 00103 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind> 00104 class CwiseBinaryOpImpl; 00105 00106 template<typename BinaryOp, typename Lhs, typename Rhs> 00107 class CwiseBinaryOp : internal::no_assignment_operator, 00108 public CwiseBinaryOpImpl< 00109 BinaryOp, Lhs, Rhs, 00110 typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, 00111 typename internal::traits<Rhs>::StorageKind>::ret> 00112 { 00113 public: 00114 00115 typedef typename CwiseBinaryOpImpl< 00116 BinaryOp, Lhs, Rhs, 00117 typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, 00118 typename internal::traits<Rhs>::StorageKind>::ret>::Base Base; 00119 EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp) 00120 00121 typedef typename internal::nested<Lhs>::type LhsNested; 00122 typedef typename internal::nested<Rhs>::type RhsNested; 00123 typedef typename internal::remove_reference<LhsNested>::type _LhsNested; 00124 typedef typename internal::remove_reference<RhsNested>::type _RhsNested; 00125 00126 EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp()) 00127 : m_lhs(aLhs), m_rhs(aRhs), m_functor(func) 00128 { 00129 EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar); 00130 // require the sizes to match 00131 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) 00132 eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()); 00133 } 00134 00135 EIGEN_STRONG_INLINE Index rows() const { 00136 // return the fixed size type if available to enable compile time optimizations 00137 if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic) 00138 return m_rhs.rows(); 00139 else 00140 return m_lhs.rows(); 00141 } 00142 EIGEN_STRONG_INLINE Index cols() const { 00143 // return the fixed size type if available to enable compile time optimizations 00144 if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic) 00145 return m_rhs.cols(); 00146 else 00147 return m_lhs.cols(); 00148 } 00149 00150 /** \returns the left hand side nested expression */ 00151 const _LhsNested& lhs () const { return m_lhs; } 00152 /** \returns the right hand side nested expression */ 00153 const _RhsNested& rhs () const { return m_rhs; } 00154 /** \returns the functor representing the binary operation */ 00155 const BinaryOp& functor () const { return m_functor; } 00156 00157 protected: 00158 LhsNested m_lhs; 00159 RhsNested m_rhs; 00160 const BinaryOp m_functor; 00161 }; 00162 00163 template<typename BinaryOp, typename Lhs, typename Rhs> 00164 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense> 00165 : public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type 00166 { 00167 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived; 00168 public: 00169 00170 typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base; 00171 EIGEN_DENSE_PUBLIC_INTERFACE( Derived ) 00172 00173 EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const 00174 { 00175 return derived().functor()(derived().lhs().coeff(rowId, colId), 00176 derived().rhs().coeff(rowId, colId)); 00177 } 00178 00179 template<int LoadMode> 00180 EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const 00181 { 00182 return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(rowId, colId), 00183 derived().rhs().template packet<LoadMode>(rowId, colId)); 00184 } 00185 00186 EIGEN_STRONG_INLINE const Scalar coeff(Index index) const 00187 { 00188 return derived().functor()(derived().lhs().coeff(index), 00189 derived().rhs().coeff(index)); 00190 } 00191 00192 template<int LoadMode> 00193 EIGEN_STRONG_INLINE PacketScalar packet(Index index) const 00194 { 00195 return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index), 00196 derived().rhs().template packet<LoadMode>(index)); 00197 } 00198 }; 00199 00200 /** replaces \c *this by \c *this - \a other. 00201 * 00202 * \returns a reference to \c *this 00203 */ 00204 template<typename Derived> 00205 template<typename OtherDerived> 00206 EIGEN_STRONG_INLINE Derived & 00207 MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other) 00208 { 00209 SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived()); 00210 tmp = other.derived(); 00211 return derived(); 00212 } 00213 00214 /** replaces \c *this by \c *this + \a other. 00215 * 00216 * \returns a reference to \c *this 00217 */ 00218 template<typename Derived> 00219 template<typename OtherDerived> 00220 EIGEN_STRONG_INLINE Derived & 00221 MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other) 00222 { 00223 SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived()); 00224 tmp = other.derived(); 00225 return derived(); 00226 } 00227 00228 } // end namespace Eigen 00229 00230 #endif // EIGEN_CWISE_BINARY_OP_H
Generated on Tue Jul 12 2022 17:46:51 by 1.7.2