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@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:
NoAlias(ExpressionType & expression)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 #endif
84
85 protected:
86 ExpressionType& m_expression;
87 };
88
89 /** \returns a pseudo expression of \c *this with an operator= assuming
90 * no aliasing between \c *this and the source expression.
91 *
92 * More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag.
93 * Currently, even though several expressions may alias, only product
94 * expressions have this flag. Therefore, noalias() is only usefull when
95 * the source expression contains a matrix product.
96 *
97 * Here are some examples where noalias is usefull:
98 * \code
99 * D.noalias() = A * B;
100 * D.noalias() += A.transpose() * B;
101 * D.noalias() -= 2 * A * B.adjoint();
102 * \endcode
103 *
104 * On the other hand the following example will lead to a \b wrong result:
105 * \code
106 * A.noalias() = A * B;
107 * \endcode
108 * because the result matrix A is also an operand of the matrix product. Therefore,
109 * there is no alternative than evaluating A * B in a temporary, that is the default
110 * behavior when you write:
111 * \code
112 * A = A * B;
113 * \endcode
114 *
115 * \sa class NoAlias
116 */
117 template<typename Derived>
noalias()118 NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias()
119 {
120 return derived();
121 }
122
123 } // end namespace Eigen
124
125 #endif // EIGEN_NOALIAS_H
126