$treeview $search $mathjax
Eigen
3.2.5
$projectbrief
|
$projectbrief
|
$searchbox |
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 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 CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost 00085 }; 00086 }; 00087 } // end namespace internal 00088 00089 // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor 00090 // that would take two operands of different types. If there were such an example, then this check should be 00091 // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as 00092 // currently they take only one typename Scalar template parameter. 00093 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. 00094 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to 00095 // add together a float matrix and a double matrix. 00096 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ 00097 EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \ 00098 ? int(internal::scalar_product_traits<LHS, RHS>::Defined) \ 00099 : int(internal::is_same<LHS, RHS>::value)), \ 00100 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 00101 00102 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind> 00103 class CwiseBinaryOpImpl; 00104 00105 template<typename BinaryOp, typename Lhs, typename Rhs> 00106 class CwiseBinaryOp : internal::no_assignment_operator, 00107 public CwiseBinaryOpImpl< 00108 BinaryOp, Lhs, Rhs, 00109 typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, 00110 typename internal::traits<Rhs>::StorageKind>::ret> 00111 { 00112 public: 00113 00114 typedef typename CwiseBinaryOpImpl< 00115 BinaryOp, Lhs, Rhs, 00116 typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, 00117 typename internal::traits<Rhs>::StorageKind>::ret>::Base Base; 00118 EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp) 00119 00120 typedef typename internal::nested<Lhs>::type LhsNested; 00121 typedef typename internal::nested<Rhs>::type RhsNested; 00122 typedef typename internal::remove_reference<LhsNested>::type _LhsNested; 00123 typedef typename internal::remove_reference<RhsNested>::type _RhsNested; 00124 00125 EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp()) 00126 : m_lhs(aLhs), m_rhs(aRhs), m_functor(func) 00127 { 00128 EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar); 00129 // require the sizes to match 00130 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) 00131 eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()); 00132 } 00133 00134 EIGEN_STRONG_INLINE Index rows() const { 00135 // return the fixed size type if available to enable compile time optimizations 00136 if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic) 00137 return m_rhs.rows(); 00138 else 00139 return m_lhs.rows(); 00140 } 00141 EIGEN_STRONG_INLINE Index cols() const { 00142 // return the fixed size type if available to enable compile time optimizations 00143 if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic) 00144 return m_rhs.cols(); 00145 else 00146 return m_lhs.cols(); 00147 } 00148 00150 const _LhsNested& lhs() const { return m_lhs; } 00152 const _RhsNested& rhs() const { return m_rhs; } 00154 const BinaryOp& functor() const { return m_functor; } 00155 00156 protected: 00157 LhsNested m_lhs; 00158 RhsNested m_rhs; 00159 const BinaryOp m_functor; 00160 }; 00161 00162 template<typename BinaryOp, typename Lhs, typename Rhs> 00163 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense> 00164 : public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type 00165 { 00166 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived; 00167 public: 00168 00169 typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base; 00170 EIGEN_DENSE_PUBLIC_INTERFACE( Derived ) 00171 00172 EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const 00173 { 00174 return derived().functor()(derived().lhs().coeff(rowId, colId), 00175 derived().rhs().coeff(rowId, colId)); 00176 } 00177 00178 template<int LoadMode> 00179 EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const 00180 { 00181 return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(rowId, colId), 00182 derived().rhs().template packet<LoadMode>(rowId, colId)); 00183 } 00184 00185 EIGEN_STRONG_INLINE const Scalar coeff(Index index) const 00186 { 00187 return derived().functor()(derived().lhs().coeff(index), 00188 derived().rhs().coeff(index)); 00189 } 00190 00191 template<int LoadMode> 00192 EIGEN_STRONG_INLINE PacketScalar packet(Index index) const 00193 { 00194 return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index), 00195 derived().rhs().template packet<LoadMode>(index)); 00196 } 00197 }; 00198 00203 template<typename Derived> 00204 template<typename OtherDerived> 00205 EIGEN_STRONG_INLINE Derived & 00206 MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other) 00207 { 00208 SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived()); 00209 tmp = other.derived(); 00210 return derived(); 00211 } 00212 00217 template<typename Derived> 00218 template<typename OtherDerived> 00219 EIGEN_STRONG_INLINE Derived & 00220 MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other) 00221 { 00222 SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived()); 00223 tmp = other.derived(); 00224 return derived(); 00225 } 00226 00227 } // end namespace Eigen 00228 00229 #endif // EIGEN_CWISE_BINARY_OP_H