1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
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_SWAP_H
11 #define EIGEN_SWAP_H
12 
13 namespace Eigen {
14 
15 /** \class SwapWrapper
16   * \ingroup Core_Module
17   *
18   * \internal
19   *
20   * \brief Internal helper class for swapping two expressions
21   */
22 namespace internal {
23 template<typename ExpressionType>
24 struct traits<SwapWrapper<ExpressionType> > : traits<ExpressionType> {};
25 }
26 
27 template<typename ExpressionType> class SwapWrapper
28   : public internal::dense_xpr_base<SwapWrapper<ExpressionType> >::type
29 {
30   public:
31 
32     typedef typename internal::dense_xpr_base<SwapWrapper>::type Base;
33     EIGEN_DENSE_PUBLIC_INTERFACE(SwapWrapper)
34     typedef typename internal::packet_traits<Scalar>::type Packet;
35 
36     inline SwapWrapper(ExpressionType& xpr) : m_expression(xpr) {}
37 
38     inline Index rows() const { return m_expression.rows(); }
39     inline Index cols() const { return m_expression.cols(); }
40     inline Index outerStride() const { return m_expression.outerStride(); }
41     inline Index innerStride() const { return m_expression.innerStride(); }
42 
43     typedef typename internal::conditional<
44                        internal::is_lvalue<ExpressionType>::value,
45                        Scalar,
46                        const Scalar
47                      >::type ScalarWithConstIfNotLvalue;
48 
49     inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
50     inline const Scalar* data() const { return m_expression.data(); }
51 
52     inline Scalar& coeffRef(Index rowId, Index colId)
53     {
54       return m_expression.const_cast_derived().coeffRef(rowId, colId);
55     }
56 
57     inline Scalar& coeffRef(Index index)
58     {
59       return m_expression.const_cast_derived().coeffRef(index);
60     }
61 
62     inline Scalar& coeffRef(Index rowId, Index colId) const
63     {
64       return m_expression.coeffRef(rowId, colId);
65     }
66 
67     inline Scalar& coeffRef(Index index) const
68     {
69       return m_expression.coeffRef(index);
70     }
71 
72     template<typename OtherDerived>
73     void copyCoeff(Index rowId, Index colId, const DenseBase<OtherDerived>& other)
74     {
75       OtherDerived& _other = other.const_cast_derived();
76       eigen_internal_assert(rowId >= 0 && rowId < rows()
77                          && colId >= 0 && colId < cols());
78       Scalar tmp = m_expression.coeff(rowId, colId);
79       m_expression.coeffRef(rowId, colId) = _other.coeff(rowId, colId);
80       _other.coeffRef(rowId, colId) = tmp;
81     }
82 
83     template<typename OtherDerived>
84     void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
85     {
86       OtherDerived& _other = other.const_cast_derived();
87       eigen_internal_assert(index >= 0 && index < m_expression.size());
88       Scalar tmp = m_expression.coeff(index);
89       m_expression.coeffRef(index) = _other.coeff(index);
90       _other.coeffRef(index) = tmp;
91     }
92 
93     template<typename OtherDerived, int StoreMode, int LoadMode>
94     void copyPacket(Index rowId, Index colId, const DenseBase<OtherDerived>& other)
95     {
96       OtherDerived& _other = other.const_cast_derived();
97       eigen_internal_assert(rowId >= 0 && rowId < rows()
98                         && colId >= 0 && colId < cols());
99       Packet tmp = m_expression.template packet<StoreMode>(rowId, colId);
100       m_expression.template writePacket<StoreMode>(rowId, colId,
101         _other.template packet<LoadMode>(rowId, colId)
102       );
103       _other.template writePacket<LoadMode>(rowId, colId, tmp);
104     }
105 
106     template<typename OtherDerived, int StoreMode, int LoadMode>
107     void copyPacket(Index index, const DenseBase<OtherDerived>& other)
108     {
109       OtherDerived& _other = other.const_cast_derived();
110       eigen_internal_assert(index >= 0 && index < m_expression.size());
111       Packet tmp = m_expression.template packet<StoreMode>(index);
112       m_expression.template writePacket<StoreMode>(index,
113         _other.template packet<LoadMode>(index)
114       );
115       _other.template writePacket<LoadMode>(index, tmp);
116     }
117 
118     ExpressionType& expression() const { return m_expression; }
119 
120   protected:
121     ExpressionType& m_expression;
122 };
123 
124 } // end namespace Eigen
125 
126 #endif // EIGEN_SWAP_H
127