CwiseBinaryOp.h
Go to the documentation of this file.
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


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 11:58:04