DenseCoeffsBase.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) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
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_DENSECOEFFSBASE_H
26 #define EIGEN_DENSECOEFFSBASE_H
27 
28 namespace Eigen {
29 
30 namespace internal {
31 template<typename T> struct add_const_on_value_type_if_arithmetic
32 {
33  typedef typename conditional<is_arithmetic<T>::value, T, typename add_const_on_value_type<T>::type>::type type;
34 };
35 }
36 
48 template<typename Derived>
49 class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
50 {
51  public:
52  typedef typename internal::traits<Derived>::StorageKind StorageKind;
53  typedef typename internal::traits<Derived>::Index Index;
54  typedef typename internal::traits<Derived>::Scalar Scalar;
55  typedef typename internal::packet_traits<Scalar>::type PacketScalar;
56 
57  // Explanation for this CoeffReturnType typedef.
58  // - This is the return type of the coeff() method.
59  // - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references
60  // to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value).
61  // - The is_artihmetic check is required since "const int", "const double", etc. will cause warnings on some systems
62  // while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is
63  // not possible, since the underlying expressions might not offer a valid address the reference could be referring to.
64  typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit),
65  const Scalar&,
66  typename internal::conditional<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>::type
67  >::type CoeffReturnType;
68 
69  typedef typename internal::add_const_on_value_type_if_arithmetic<
70  typename internal::packet_traits<Scalar>::type
72 
74  using Base::rows;
75  using Base::cols;
76  using Base::size;
77  using Base::derived;
78 
79  EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const
80  {
81  return int(Derived::RowsAtCompileTime) == 1 ? 0
82  : int(Derived::ColsAtCompileTime) == 1 ? inner
83  : int(Derived::Flags)&RowMajorBit ? outer
84  : inner;
85  }
86 
87  EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const
88  {
89  return int(Derived::ColsAtCompileTime) == 1 ? 0
90  : int(Derived::RowsAtCompileTime) == 1 ? inner
91  : int(Derived::Flags)&RowMajorBit ? inner
92  : outer;
93  }
94 
110  {
111  eigen_internal_assert(row >= 0 && row < rows()
112  && col >= 0 && col < cols());
113  return derived().coeff(row, col);
114  }
115 
116  EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const
117  {
118  return coeff(rowIndexByOuterInner(outer, inner),
119  colIndexByOuterInner(outer, inner));
120  }
121 
127  {
128  eigen_assert(row >= 0 && row < rows()
129  && col >= 0 && col < cols());
130  return derived().coeff(row, col);
131  }
132 
148  EIGEN_STRONG_INLINE CoeffReturnType
149  coeff(Index index) const
150  {
151  eigen_internal_assert(index >= 0 && index < size());
152  return derived().coeff(index);
153  }
154 
155 
164  EIGEN_STRONG_INLINE CoeffReturnType
165  operator[](Index index) const
166  {
167  #ifndef EIGEN2_SUPPORT
168  EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
169  THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
170  #endif
171  eigen_assert(index >= 0 && index < size());
172  return derived().coeff(index);
173  }
174 
185  EIGEN_STRONG_INLINE CoeffReturnType
186  operator()(Index index) const
187  {
188  eigen_assert(index >= 0 && index < size());
189  return derived().coeff(index);
190  }
191 
194  EIGEN_STRONG_INLINE CoeffReturnType
195  x() const { return (*this)[0]; }
196 
199  EIGEN_STRONG_INLINE CoeffReturnType
200  y() const { return (*this)[1]; }
201 
204  EIGEN_STRONG_INLINE CoeffReturnType
205  z() const { return (*this)[2]; }
206 
209  EIGEN_STRONG_INLINE CoeffReturnType
210  w() const { return (*this)[3]; }
211 
222  template<int LoadMode>
224  {
225  eigen_internal_assert(row >= 0 && row < rows()
226  && col >= 0 && col < cols());
227  return derived().template packet<LoadMode>(row,col);
228  }
229 
230 
232  template<int LoadMode>
233  EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const
234  {
235  return packet<LoadMode>(rowIndexByOuterInner(outer, inner),
236  colIndexByOuterInner(outer, inner));
237  }
238 
249  template<int LoadMode>
251  {
252  eigen_internal_assert(index >= 0 && index < size());
253  return derived().template packet<LoadMode>(index);
254  }
255 
256  protected:
257  // explanation: DenseBase is doing "using ..." on the methods from DenseCoeffsBase.
258  // But some methods are only available in the DirectAccess case.
259  // So we add dummy methods here with these names, so that "using... " doesn't fail.
260  // It's not private so that the child class DenseBase can access them, and it's not public
261  // either since it's an implementation detail, so has to be protected.
262  void coeffRef();
263  void coeffRefByOuterInner();
264  void writePacket();
265  void writePacketByOuterInner();
266  void copyCoeff();
267  void copyCoeffByOuterInner();
268  void copyPacket();
269  void copyPacketByOuterInner();
270  void stride();
271  void innerStride();
272  void outerStride();
273  void rowStride();
274  void colStride();
275 };
276 
288 template<typename Derived>
289 class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
290 {
291  public:
292 
294 
295  typedef typename internal::traits<Derived>::StorageKind StorageKind;
296  typedef typename internal::traits<Derived>::Index Index;
297  typedef typename internal::traits<Derived>::Scalar Scalar;
298  typedef typename internal::packet_traits<Scalar>::type PacketScalar;
300 
301  using Base::coeff;
302  using Base::rows;
303  using Base::cols;
304  using Base::size;
305  using Base::derived;
306  using Base::rowIndexByOuterInner;
307  using Base::colIndexByOuterInner;
308  using Base::operator[];
309  using Base::operator();
310  using Base::x;
311  using Base::y;
312  using Base::z;
313  using Base::w;
314 
330  {
331  eigen_internal_assert(row >= 0 && row < rows()
332  && col >= 0 && col < cols());
333  return derived().coeffRef(row, col);
334  }
335 
336  EIGEN_STRONG_INLINE Scalar&
337  coeffRefByOuterInner(Index outer, Index inner)
338  {
339  return coeffRef(rowIndexByOuterInner(outer, inner),
340  colIndexByOuterInner(outer, inner));
341  }
342 
348  EIGEN_STRONG_INLINE Scalar&
349  operator()(Index row, Index col)
350  {
351  eigen_assert(row >= 0 && row < rows()
352  && col >= 0 && col < cols());
353  return derived().coeffRef(row, col);
354  }
355 
356 
372  EIGEN_STRONG_INLINE Scalar&
373  coeffRef(Index index)
374  {
375  eigen_internal_assert(index >= 0 && index < size());
376  return derived().coeffRef(index);
377  }
378 
386  EIGEN_STRONG_INLINE Scalar&
387  operator[](Index index)
388  {
389  #ifndef EIGEN2_SUPPORT
390  EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
391  THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
392  #endif
393  eigen_assert(index >= 0 && index < size());
394  return derived().coeffRef(index);
395  }
396 
406  EIGEN_STRONG_INLINE Scalar&
407  operator()(Index index)
408  {
409  eigen_assert(index >= 0 && index < size());
410  return derived().coeffRef(index);
411  }
412 
415  EIGEN_STRONG_INLINE Scalar&
416  x() { return (*this)[0]; }
417 
420  EIGEN_STRONG_INLINE Scalar&
421  y() { return (*this)[1]; }
422 
425  EIGEN_STRONG_INLINE Scalar&
426  z() { return (*this)[2]; }
427 
430  EIGEN_STRONG_INLINE Scalar&
431  w() { return (*this)[3]; }
432 
443  template<int StoreMode>
444  EIGEN_STRONG_INLINE void writePacket
445  (Index row, Index col, const typename internal::packet_traits<Scalar>::type& x)
446  {
447  eigen_internal_assert(row >= 0 && row < rows()
448  && col >= 0 && col < cols());
449  derived().template writePacket<StoreMode>(row,col,x);
450  }
451 
452 
454  template<int StoreMode>
455  EIGEN_STRONG_INLINE void writePacketByOuterInner
456  (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x)
457  {
458  writePacket<StoreMode>(rowIndexByOuterInner(outer, inner),
459  colIndexByOuterInner(outer, inner),
460  x);
461  }
462 
472  template<int StoreMode>
473  EIGEN_STRONG_INLINE void writePacket
474  (Index index, const typename internal::packet_traits<Scalar>::type& x)
475  {
476  eigen_internal_assert(index >= 0 && index < size());
477  derived().template writePacket<StoreMode>(index,x);
478  }
479 
480 #ifndef EIGEN_PARSED_BY_DOXYGEN
481 
490  template<typename OtherDerived>
491  EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
492  {
493  eigen_internal_assert(row >= 0 && row < rows()
494  && col >= 0 && col < cols());
495  derived().coeffRef(row, col) = other.derived().coeff(row, col);
496  }
497 
506  template<typename OtherDerived>
507  EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
508  {
509  eigen_internal_assert(index >= 0 && index < size());
510  derived().coeffRef(index) = other.derived().coeff(index);
511  }
512 
513 
514  template<typename OtherDerived>
515  EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
516  {
517  const Index row = rowIndexByOuterInner(outer,inner);
518  const Index col = colIndexByOuterInner(outer,inner);
519  // derived() is important here: copyCoeff() may be reimplemented in Derived!
520  derived().copyCoeff(row, col, other);
521  }
522 
531  template<typename OtherDerived, int StoreMode, int LoadMode>
532  EIGEN_STRONG_INLINE void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
533  {
534  eigen_internal_assert(row >= 0 && row < rows()
535  && col >= 0 && col < cols());
536  derived().template writePacket<StoreMode>(row, col,
537  other.derived().template packet<LoadMode>(row, col));
538  }
539 
548  template<typename OtherDerived, int StoreMode, int LoadMode>
549  EIGEN_STRONG_INLINE void copyPacket(Index index, const DenseBase<OtherDerived>& other)
550  {
551  eigen_internal_assert(index >= 0 && index < size());
552  derived().template writePacket<StoreMode>(index,
553  other.derived().template packet<LoadMode>(index));
554  }
555 
557  template<typename OtherDerived, int StoreMode, int LoadMode>
558  EIGEN_STRONG_INLINE void copyPacketByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
559  {
560  const Index row = rowIndexByOuterInner(outer,inner);
561  const Index col = colIndexByOuterInner(outer,inner);
562  // derived() is important here: copyCoeff() may be reimplemented in Derived!
563  derived().template copyPacket< OtherDerived, StoreMode, LoadMode>(row, col, other);
564  }
565 #endif
566 
567 };
568 
580 template<typename Derived>
581 class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
582 {
583  public:
584 
586  typedef typename internal::traits<Derived>::Index Index;
587  typedef typename internal::traits<Derived>::Scalar Scalar;
589 
590  using Base::rows;
591  using Base::cols;
592  using Base::size;
593  using Base::derived;
594 
599  inline Index innerStride() const
600  {
601  return derived().innerStride();
602  }
603 
609  inline Index outerStride() const
610  {
611  return derived().outerStride();
612  }
613 
614  // FIXME shall we remove it ?
615  inline Index stride() const
616  {
617  return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
618  }
619 
624  inline Index rowStride() const
625  {
626  return Derived::IsRowMajor ? outerStride() : innerStride();
627  }
628 
633  inline Index colStride() const
634  {
635  return Derived::IsRowMajor ? innerStride() : outerStride();
636  }
637 };
638 
650 template<typename Derived>
652  : public DenseCoeffsBase<Derived, WriteAccessors>
653 {
654  public:
655 
657  typedef typename internal::traits<Derived>::Index Index;
658  typedef typename internal::traits<Derived>::Scalar Scalar;
660 
661  using Base::rows;
662  using Base::cols;
663  using Base::size;
664  using Base::derived;
665 
670  inline Index innerStride() const
671  {
672  return derived().innerStride();
673  }
674 
680  inline Index outerStride() const
681  {
682  return derived().outerStride();
683  }
684 
685  // FIXME shall we remove it ?
686  inline Index stride() const
687  {
688  return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
689  }
690 
695  inline Index rowStride() const
696  {
697  return Derived::IsRowMajor ? outerStride() : innerStride();
698  }
699 
704  inline Index colStride() const
705  {
706  return Derived::IsRowMajor ? innerStride() : outerStride();
707  }
708 };
709 
710 namespace internal {
711 
712 template<typename Derived, bool JustReturnZero>
713 struct first_aligned_impl
714 {
715  static inline typename Derived::Index run(const Derived&)
716  { return 0; }
717 };
718 
719 template<typename Derived>
720 struct first_aligned_impl<Derived, false>
721 {
722  static inline typename Derived::Index run(const Derived& m)
723  {
724  return internal::first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size());
725  }
726 };
727 
733 template<typename Derived>
734 static inline typename Derived::Index first_aligned(const Derived& m)
735 {
736  return first_aligned_impl
737  <Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)>
738  ::run(m);
739 }
740 
741 template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
742 struct inner_stride_at_compile_time
743 {
745 };
746 
747 template<typename Derived>
748 struct inner_stride_at_compile_time<Derived, false>
749 {
750  enum { ret = 0 };
751 };
752 
753 template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
754 struct outer_stride_at_compile_time
755 {
757 };
758 
759 template<typename Derived>
760 struct outer_stride_at_compile_time<Derived, false>
761 {
762  enum { ret = 0 };
763 };
764 
765 } // end namespace internal
766 
767 } // end namespace Eigen
768 
769 #endif // EIGEN_DENSECOEFFSBASE_H