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
84 template<typename OtherDerived>
85 ExpressionType& operator=(const ReturnByValue<OtherDerived>& func)
86 { return m_expression = func; }
87 #endif
88
expression()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>
noalias()127 NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias()
128 {
129 return derived();
130 }
131
132 } // end namespace Eigen
133
134 #endif // EIGEN_NOALIAS_H
135