Home | History | Annotate | Download | only in Core
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_NOALIAS_H
     11 #define EIGEN_NOALIAS_H
     12 
     13 namespace Eigen {
     14 
     15 /** \class NoAlias
     16   * \ingroup Core_Module
     17   *
     18   * \brief Pseudo expression providing an operator = assuming no aliasing
     19   *
     20   * \param ExpressionType the type of the object on which to do the lazy assignment
     21   *
     22   * This class represents an expression with special assignment operators
     23   * assuming no aliasing between the target expression and the source expression.
     24   * More precisely it alloas to bypass the EvalBeforeAssignBit flag of the source expression.
     25   * It is the return type of MatrixBase::noalias()
     26   * and most of the time this is the only way it is used.
     27   *
     28   * \sa MatrixBase::noalias()
     29   */
     30 template<typename ExpressionType, template <typename> class StorageBase>
     31 class NoAlias
     32 {
     33     typedef typename ExpressionType::Scalar Scalar;
     34   public:
     35     NoAlias(ExpressionType& expression) : m_expression(expression) {}
     36 
     37     /** Behaves like MatrixBase::lazyAssign(other)
     38       * \sa MatrixBase::lazyAssign() */
     39     template<typename OtherDerived>
     40     EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other)
     41     { return internal::assign_selector<ExpressionType,OtherDerived,false>::run(m_expression,other.derived()); }
     42 
     43     /** \sa MatrixBase::operator+= */
     44     template<typename OtherDerived>
     45     EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other)
     46     {
     47       typedef SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
     48       SelfAdder tmp(m_expression);
     49       typedef typename internal::nested<OtherDerived>::type OtherDerivedNested;
     50       typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested;
     51       internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived()));
     52       return m_expression;
     53     }
     54 
     55     /** \sa MatrixBase::operator-= */
     56     template<typename OtherDerived>
     57     EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other)
     58     {
     59       typedef SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
     60       SelfAdder tmp(m_expression);
     61       typedef typename internal::nested<OtherDerived>::type OtherDerivedNested;
     62       typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested;
     63       internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived()));
     64       return m_expression;
     65     }
     66 
     67 #ifndef EIGEN_PARSED_BY_DOXYGEN
     68     template<typename ProductDerived, typename Lhs, typename Rhs>
     69     EIGEN_STRONG_INLINE ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
     70     { other.derived().addTo(m_expression); return m_expression; }
     71 
     72     template<typename ProductDerived, typename Lhs, typename Rhs>
     73     EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
     74     { other.derived().subTo(m_expression); return m_expression; }
     75 
     76     template<typename Lhs, typename Rhs, int NestingFlags>
     77     EIGEN_STRONG_INLINE ExpressionType& operator+=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
     78     { return m_expression.derived() += CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
     79 
     80     template<typename Lhs, typename Rhs, int NestingFlags>
     81     EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
     82     { return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
     83 
     84     template<typename OtherDerived>
     85     ExpressionType& operator=(const ReturnByValue<OtherDerived>& func)
     86     { return m_expression = func; }
     87 #endif
     88 
     89     ExpressionType& expression() const
     90     {
     91       return m_expression;
     92     }
     93 
     94   protected:
     95     ExpressionType& m_expression;
     96 };
     97 
     98 /** \returns a pseudo expression of \c *this with an operator= assuming
     99   * no aliasing between \c *this and the source expression.
    100   *
    101   * More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag.
    102   * Currently, even though several expressions may alias, only product
    103   * expressions have this flag. Therefore, noalias() is only usefull when
    104   * the source expression contains a matrix product.
    105   *
    106   * Here are some examples where noalias is usefull:
    107   * \code
    108   * D.noalias()  = A * B;
    109   * D.noalias() += A.transpose() * B;
    110   * D.noalias() -= 2 * A * B.adjoint();
    111   * \endcode
    112   *
    113   * On the other hand the following example will lead to a \b wrong result:
    114   * \code
    115   * A.noalias() = A * B;
    116   * \endcode
    117   * because the result matrix A is also an operand of the matrix product. Therefore,
    118   * there is no alternative than evaluating A * B in a temporary, that is the default
    119   * behavior when you write:
    120   * \code
    121   * A = A * B;
    122   * \endcode
    123   *
    124   * \sa class NoAlias
    125   */
    126 template<typename Derived>
    127 NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias()
    128 {
    129   return derived();
    130 }
    131 
    132 } // end namespace Eigen
    133 
    134 #endif // EIGEN_NOALIAS_H
    135