Transpositions.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2010-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef EIGEN_TRANSPOSITIONS_H
26 #define EIGEN_TRANSPOSITIONS_H
27 
28 namespace Eigen {
29 
59 namespace internal {
60 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed=false> struct transposition_matrix_product_retval;
61 }
62 
63 template<typename Derived>
65 {
66  typedef internal::traits<Derived> Traits;
67 
68  public:
69 
70  typedef typename Traits::IndicesType IndicesType;
71  typedef typename IndicesType::Scalar Index;
72 
73  Derived& derived() { return *static_cast<Derived*>(this); }
74  const Derived& derived() const { return *static_cast<const Derived*>(this); }
75 
77  template<typename OtherDerived>
79  {
80  indices() = other.indices();
81  return derived();
82  }
83 
84  #ifndef EIGEN_PARSED_BY_DOXYGEN
85 
88  Derived& operator=(const TranspositionsBase& other)
89  {
90  indices() = other.indices();
91  return derived();
92  }
93  #endif
94 
96  inline Index size() const { return indices().size(); }
97 
99  inline const Index& coeff(Index i) const { return indices().coeff(i); }
101  inline Index& coeffRef(Index i) { return indices().coeffRef(i); }
103  inline const Index& operator()(Index i) const { return indices()(i); }
105  inline Index& operator()(Index i) { return indices()(i); }
107  inline const Index& operator[](Index i) const { return indices()(i); }
109  inline Index& operator[](Index i) { return indices()(i); }
110 
112  const IndicesType& indices() const { return derived().indices(); }
114  IndicesType& indices() { return derived().indices(); }
115 
117  inline void resize(int size)
118  {
119  indices().resize(size);
120  }
121 
123  void setIdentity()
124  {
125  for(int i = 0; i < indices().size(); ++i)
126  coeffRef(i) = i;
127  }
128 
129  // FIXME: do we want such methods ?
130  // might be usefull when the target matrix expression is complex, e.g.:
131  // object.matrix().block(..,..,..,..) = trans * object.matrix().block(..,..,..,..);
132  /*
133  template<typename MatrixType>
134  void applyForwardToRows(MatrixType& mat) const
135  {
136  for(Index k=0 ; k<size() ; ++k)
137  if(m_indices(k)!=k)
138  mat.row(k).swap(mat.row(m_indices(k)));
139  }
140 
141  template<typename MatrixType>
142  void applyBackwardToRows(MatrixType& mat) const
143  {
144  for(Index k=size()-1 ; k>=0 ; --k)
145  if(m_indices(k)!=k)
146  mat.row(k).swap(mat.row(m_indices(k)));
147  }
148  */
149 
153 
157 
158  protected:
159 };
160 
161 namespace internal {
162 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
163 struct traits<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
164 {
165  typedef IndexType Index;
166  typedef Matrix<Index, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
167 };
168 }
169 
170 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
171 class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
172 {
173  typedef internal::traits<Transpositions> Traits;
174  public:
175 
178  typedef typename IndicesType::Scalar Index;
179 
180  inline Transpositions() {}
181 
183  template<typename OtherDerived>
185  : m_indices(other.indices()) {}
186 
187  #ifndef EIGEN_PARSED_BY_DOXYGEN
188 
190  inline Transpositions(const Transpositions& other) : m_indices(other.indices()) {}
191  #endif
192 
194  template<typename Other>
195  explicit inline Transpositions(const MatrixBase<Other>& indices) : m_indices(indices)
196  {}
197 
199  template<typename OtherDerived>
201  {
202  return Base::operator=(other);
203  }
204 
205  #ifndef EIGEN_PARSED_BY_DOXYGEN
206 
210  {
211  m_indices = other.m_indices;
212  return *this;
213  }
214  #endif
215 
219  {}
220 
222  const IndicesType& indices() const { return m_indices; }
225 
226  protected:
227 
229 };
230 
231 
232 namespace internal {
233 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
234 struct traits<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,_PacketAccess> >
235 {
236  typedef IndexType Index;
238 };
239 }
240 
241 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int PacketAccess>
242 class Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess>
243  : public TranspositionsBase<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess> >
244 {
245  typedef internal::traits<Map> Traits;
246  public:
247 
249  typedef typename Traits::IndicesType IndicesType;
250  typedef typename IndicesType::Scalar Index;
251 
252  inline Map(const Index* indices)
253  : m_indices(indices)
254  {}
255 
256  inline Map(const Index* indices, Index size)
257  : m_indices(indices,size)
258  {}
259 
261  template<typename OtherDerived>
262  Map& operator=(const TranspositionsBase<OtherDerived>& other)
263  {
264  return Base::operator=(other);
265  }
266 
267  #ifndef EIGEN_PARSED_BY_DOXYGEN
268 
271  Map& operator=(const Map& other)
272  {
273  m_indices = other.m_indices;
274  return *this;
275  }
276  #endif
277 
279  const IndicesType& indices() const { return m_indices; }
280 
282  IndicesType& indices() { return m_indices; }
283 
284  protected:
285 
287 };
288 
289 namespace internal {
290 template<typename _IndicesType>
291 struct traits<TranspositionsWrapper<_IndicesType> >
292 {
293  typedef typename _IndicesType::Scalar Index;
294  typedef _IndicesType IndicesType;
295 };
296 }
297 
298 template<typename _IndicesType>
300  : public TranspositionsBase<TranspositionsWrapper<_IndicesType> >
301 {
302  typedef internal::traits<TranspositionsWrapper> Traits;
303  public:
304 
306  typedef typename Traits::IndicesType IndicesType;
307  typedef typename IndicesType::Scalar Index;
308 
310  : m_indices(indices)
311  {}
312 
314  template<typename OtherDerived>
316  {
317  return Base::operator=(other);
318  }
319 
320  #ifndef EIGEN_PARSED_BY_DOXYGEN
321 
325  {
326  m_indices = other.m_indices;
327  return *this;
328  }
329  #endif
330 
332  const IndicesType& indices() const { return m_indices; }
333 
336 
337  protected:
338 
339  const typename IndicesType::Nested m_indices;
340 };
341 
344 template<typename Derived, typename TranspositionsDerived>
345 inline const internal::transposition_matrix_product_retval<TranspositionsDerived, Derived, OnTheRight>
347  const TranspositionsBase<TranspositionsDerived> &transpositions)
348 {
349  return internal::transposition_matrix_product_retval
350  <TranspositionsDerived, Derived, OnTheRight>
351  (transpositions.derived(), matrix.derived());
352 }
353 
356 template<typename Derived, typename TranspositionDerived>
357 inline const internal::transposition_matrix_product_retval
358  <TranspositionDerived, Derived, OnTheLeft>
360  const MatrixBase<Derived>& matrix)
361 {
362  return internal::transposition_matrix_product_retval
363  <TranspositionDerived, Derived, OnTheLeft>
364  (transpositions.derived(), matrix.derived());
365 }
366 
367 namespace internal {
368 
369 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
370 struct traits<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
371 {
372  typedef typename MatrixType::PlainObject ReturnType;
373 };
374 
375 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
376 struct transposition_matrix_product_retval
377  : public ReturnByValue<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
378 {
379  typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
380  typedef typename TranspositionType::Index Index;
381 
382  transposition_matrix_product_retval(const TranspositionType& tr, const MatrixType& matrix)
383  : m_transpositions(tr), m_matrix(matrix)
384  {}
385 
386  inline int rows() const { return m_matrix.rows(); }
387  inline int cols() const { return m_matrix.cols(); }
388 
389  template<typename Dest> inline void evalTo(Dest& dst) const
390  {
391  const int size = m_transpositions.size();
392  Index j = 0;
393 
394  if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
395  dst = m_matrix;
396 
397  for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
398  if((j=m_transpositions.coeff(k))!=k)
399  {
400  if(Side==OnTheLeft)
401  dst.row(k).swap(dst.row(j));
402  else if(Side==OnTheRight)
403  dst.col(k).swap(dst.col(j));
404  }
405  }
406 
407  protected:
408  const TranspositionType& m_transpositions;
409  typename MatrixType::Nested m_matrix;
410 };
411 
412 } // end namespace internal
413 
414 /* Template partial specialization for transposed/inverse transpositions */
415 
416 template<typename TranspositionsDerived>
417 class Transpose<TranspositionsBase<TranspositionsDerived> >
418 {
419  typedef TranspositionsDerived TranspositionType;
420  typedef typename TranspositionType::IndicesType IndicesType;
421  public:
422 
423  Transpose(const TranspositionType& t) : m_transpositions(t) {}
424 
425  inline int size() const { return m_transpositions.size(); }
426 
429  template<typename Derived> friend
430  inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>
431  operator*(const MatrixBase<Derived>& matrix, const Transpose& trt)
432  {
433  return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>(trt.m_transpositions, matrix.derived());
434  }
435 
438  template<typename Derived>
439  inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>
440  operator*(const MatrixBase<Derived>& matrix) const
441  {
442  return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>(m_transpositions, matrix.derived());
443  }
444 
445  protected:
446  const TranspositionType& m_transpositions;
447 };
448 
449 } // end namespace Eigen
450 
451 #endif // EIGEN_TRANSPOSITIONS_H