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 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #ifndef EIGEN_CWISE_BINARY_OP_H
00027 #define EIGEN_CWISE_BINARY_OP_H
00028 
00049 namespace internal {
00050 template<typename BinaryOp, typename Lhs, typename Rhs>
00051 struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00052 {
00053   // we must not inherit from traits<Lhs> since it has
00054   // the potential to cause problems with MSVC
00055   typedef typename remove_all<Lhs>::type Ancestor;
00056   typedef typename traits<Ancestor>::XprKind XprKind;
00057   enum {
00058     RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
00059     ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
00060     MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
00061     MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
00062   };
00063 
00064   // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor),
00065   // we still want to handle the case when the result type is different.
00066   typedef typename result_of<
00067                      BinaryOp(
00068                        typename Lhs::Scalar,
00069                        typename Rhs::Scalar
00070                      )
00071                    >::type Scalar;
00072   typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
00073                                            typename traits<Rhs>::StorageKind>::ret StorageKind;
00074   typedef typename promote_index_type<typename traits<Lhs>::Index,
00075                                          typename traits<Rhs>::Index>::type Index;
00076   typedef typename Lhs::Nested LhsNested;
00077   typedef typename Rhs::Nested RhsNested;
00078   typedef typename remove_reference<LhsNested>::type _LhsNested;
00079   typedef typename remove_reference<RhsNested>::type _RhsNested;
00080   enum {
00081     LhsCoeffReadCost = _LhsNested::CoeffReadCost,
00082     RhsCoeffReadCost = _RhsNested::CoeffReadCost,
00083     LhsFlags = _LhsNested::Flags,
00084     RhsFlags = _RhsNested::Flags,
00085     SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
00086     StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit),
00087     Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
00088         HereditaryBits
00089       | (int(LhsFlags) & int(RhsFlags) &
00090            ( AlignedBit
00091            | (StorageOrdersAgree ? LinearAccessBit : 0)
00092            | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
00093            )
00094         )
00095      ),
00096     Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
00097     CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
00098   };
00099 };
00100 } // end namespace internal
00101 
00102 // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
00103 // that would take two operands of different types. If there were such an example, then this check should be
00104 // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
00105 // currently they take only one typename Scalar template parameter.
00106 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
00107 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
00108 // add together a float matrix and a double matrix.
00109 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
00110   EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
00111                         ? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
00112                         : int(internal::is_same<LHS, RHS>::value)), \
00113     YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00114 
00115 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
00116 class CwiseBinaryOpImpl;
00117 
00118 template<typename BinaryOp, typename Lhs, typename Rhs>
00119 class CwiseBinaryOp : internal::no_assignment_operator,
00120   public CwiseBinaryOpImpl<
00121           BinaryOp, Lhs, Rhs,
00122           typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
00123                                            typename internal::traits<Rhs>::StorageKind>::ret>
00124 {
00125   public:
00126 
00127     typedef typename CwiseBinaryOpImpl<
00128         BinaryOp, Lhs, Rhs,
00129         typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
00130                                          typename internal::traits<Rhs>::StorageKind>::ret>::Base Base;
00131     EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
00132 
00133     typedef typename internal::nested<Lhs>::type LhsNested;
00134     typedef typename internal::nested<Rhs>::type RhsNested;
00135     typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
00136     typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
00137 
00138     EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
00139       : m_lhs(lhs), m_rhs(rhs), m_functor(func)
00140     {
00141       EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
00142       // require the sizes to match
00143       EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
00144       eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
00145     }
00146 
00147     EIGEN_STRONG_INLINE Index rows() const {
00148       // return the fixed size type if available to enable compile time optimizations
00149       if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic)
00150         return m_rhs.rows();
00151       else
00152         return m_lhs.rows();
00153     }
00154     EIGEN_STRONG_INLINE Index cols() const {
00155       // return the fixed size type if available to enable compile time optimizations
00156       if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic)
00157         return m_rhs.cols();
00158       else
00159         return m_lhs.cols();
00160     }
00161 
00163     const _LhsNested& lhs() const { return m_lhs; }
00165     const _RhsNested& rhs() const { return m_rhs; }
00167     const BinaryOp& functor() const { return m_functor; }
00168 
00169   protected:
00170     const LhsNested m_lhs;
00171     const RhsNested m_rhs;
00172     const BinaryOp m_functor;
00173 };
00174 
00175 template<typename BinaryOp, typename Lhs, typename Rhs>
00176 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
00177   : public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
00178 {
00179     typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
00180   public:
00181 
00182     typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
00183     EIGEN_DENSE_PUBLIC_INTERFACE( Derived )
00184 
00185     EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
00186     {
00187       return derived().functor()(derived().lhs().coeff(row, col),
00188                                  derived().rhs().coeff(row, col));
00189     }
00190 
00191     template<int LoadMode>
00192     EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
00193     {
00194       return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col),
00195                                           derived().rhs().template packet<LoadMode>(row, col));
00196     }
00197 
00198     EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
00199     {
00200       return derived().functor()(derived().lhs().coeff(index),
00201                                  derived().rhs().coeff(index));
00202     }
00203 
00204     template<int LoadMode>
00205     EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
00206     {
00207       return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index),
00208                                           derived().rhs().template packet<LoadMode>(index));
00209     }
00210 };
00211 
00216 template<typename Derived>
00217 template<typename OtherDerived>
00218 EIGEN_STRONG_INLINE Derived &
00219 MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
00220 {
00221   SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived());
00222   tmp = other.derived();
00223   return derived();
00224 }
00225 
00230 template<typename Derived>
00231 template<typename OtherDerived>
00232 EIGEN_STRONG_INLINE Derived &
00233 MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
00234 {
00235   SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived());
00236   tmp = other.derived();
00237   return derived();
00238 }
00239 
00240 #endif // EIGEN_CWISE_BINARY_OP_H


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:00