DenseCoeffsBase.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #ifndef EIGEN_DENSECOEFFSBASE_H
00026 #define EIGEN_DENSECOEFFSBASE_H
00027 
00028 namespace Eigen {
00029 
00030 namespace internal {
00031 template<typename T> struct add_const_on_value_type_if_arithmetic
00032 {
00033   typedef typename conditional<is_arithmetic<T>::value, T, typename add_const_on_value_type<T>::type>::type type;
00034 };
00035 }
00036 
00048 template<typename Derived>
00049 class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
00050 {
00051   public:
00052     typedef typename internal::traits<Derived>::StorageKind StorageKind;
00053     typedef typename internal::traits<Derived>::Index Index;
00054     typedef typename internal::traits<Derived>::Scalar Scalar;
00055     typedef typename internal::packet_traits<Scalar>::type PacketScalar;
00056 
00057     // Explanation for this CoeffReturnType typedef.
00058     // - This is the return type of the coeff() method.
00059     // - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references
00060     // to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value).
00061     // - The is_artihmetic check is required since "const int", "const double", etc. will cause warnings on some systems
00062     // while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is
00063     // not possible, since the underlying expressions might not offer a valid address the reference could be referring to.
00064     typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit),
00065                          const Scalar&,
00066                          typename internal::conditional<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>::type
00067                      >::type CoeffReturnType;
00068 
00069     typedef typename internal::add_const_on_value_type_if_arithmetic<
00070                          typename internal::packet_traits<Scalar>::type
00071                      >::type PacketReturnType;
00072 
00073     typedef EigenBase<Derived> Base;
00074     using Base::rows;
00075     using Base::cols;
00076     using Base::size;
00077     using Base::derived;
00078 
00079     EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const
00080     {
00081       return int(Derived::RowsAtCompileTime) == 1 ? 0
00082           : int(Derived::ColsAtCompileTime) == 1 ? inner
00083           : int(Derived::Flags)&RowMajorBit ? outer
00084           : inner;
00085     }
00086 
00087     EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const
00088     {
00089       return int(Derived::ColsAtCompileTime) == 1 ? 0
00090           : int(Derived::RowsAtCompileTime) == 1 ? inner
00091           : int(Derived::Flags)&RowMajorBit ? inner
00092           : outer;
00093     }
00094 
00109     EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
00110     {
00111       eigen_internal_assert(row >= 0 && row < rows()
00112                         && col >= 0 && col < cols());
00113       return derived().coeff(row, col);
00114     }
00115 
00116     EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const
00117     {
00118       return coeff(rowIndexByOuterInner(outer, inner),
00119                    colIndexByOuterInner(outer, inner));
00120     }
00121 
00126     EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
00127     {
00128       eigen_assert(row >= 0 && row < rows()
00129           && col >= 0 && col < cols());
00130       return derived().coeff(row, col);
00131     }
00132 
00148     EIGEN_STRONG_INLINE CoeffReturnType
00149     coeff(Index index) const
00150     {
00151       eigen_internal_assert(index >= 0 && index < size());
00152       return derived().coeff(index);
00153     }
00154 
00155 
00164     EIGEN_STRONG_INLINE CoeffReturnType
00165     operator[](Index index) const
00166     {
00167       #ifndef EIGEN2_SUPPORT
00168       EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
00169                           THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
00170       #endif
00171       eigen_assert(index >= 0 && index < size());
00172       return derived().coeff(index);
00173     }
00174 
00185     EIGEN_STRONG_INLINE CoeffReturnType
00186     operator()(Index index) const
00187     {
00188       eigen_assert(index >= 0 && index < size());
00189       return derived().coeff(index);
00190     }
00191 
00194     EIGEN_STRONG_INLINE CoeffReturnType
00195     x() const { return (*this)[0]; }
00196 
00199     EIGEN_STRONG_INLINE CoeffReturnType
00200     y() const { return (*this)[1]; }
00201 
00204     EIGEN_STRONG_INLINE CoeffReturnType
00205     z() const { return (*this)[2]; }
00206 
00209     EIGEN_STRONG_INLINE CoeffReturnType
00210     w() const { return (*this)[3]; }
00211 
00222     template<int LoadMode>
00223     EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const
00224     {
00225       eigen_internal_assert(row >= 0 && row < rows()
00226                       && col >= 0 && col < cols());
00227       return derived().template packet<LoadMode>(row,col);
00228     }
00229 
00230 
00232     template<int LoadMode>
00233     EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const
00234     {
00235       return packet<LoadMode>(rowIndexByOuterInner(outer, inner),
00236                               colIndexByOuterInner(outer, inner));
00237     }
00238 
00249     template<int LoadMode>
00250     EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
00251     {
00252       eigen_internal_assert(index >= 0 && index < size());
00253       return derived().template packet<LoadMode>(index);
00254     }
00255 
00256   protected:
00257     // explanation: DenseBase is doing "using ..." on the methods from DenseCoeffsBase.
00258     // But some methods are only available in the DirectAccess case.
00259     // So we add dummy methods here with these names, so that "using... " doesn't fail.
00260     // It's not private so that the child class DenseBase can access them, and it's not public
00261     // either since it's an implementation detail, so has to be protected.
00262     void coeffRef();
00263     void coeffRefByOuterInner();
00264     void writePacket();
00265     void writePacketByOuterInner();
00266     void copyCoeff();
00267     void copyCoeffByOuterInner();
00268     void copyPacket();
00269     void copyPacketByOuterInner();
00270     void stride();
00271     void innerStride();
00272     void outerStride();
00273     void rowStride();
00274     void colStride();
00275 };
00276 
00288 template<typename Derived>
00289 class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
00290 {
00291   public:
00292 
00293     typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base;
00294 
00295     typedef typename internal::traits<Derived>::StorageKind StorageKind;
00296     typedef typename internal::traits<Derived>::Index Index;
00297     typedef typename internal::traits<Derived>::Scalar Scalar;
00298     typedef typename internal::packet_traits<Scalar>::type PacketScalar;
00299     typedef typename NumTraits<Scalar>::Real RealScalar;
00300 
00301     using Base::coeff;
00302     using Base::rows;
00303     using Base::cols;
00304     using Base::size;
00305     using Base::derived;
00306     using Base::rowIndexByOuterInner;
00307     using Base::colIndexByOuterInner;
00308     using Base::operator[];
00309     using Base::operator();
00310     using Base::x;
00311     using Base::y;
00312     using Base::z;
00313     using Base::w;
00314 
00329     EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
00330     {
00331       eigen_internal_assert(row >= 0 && row < rows()
00332                         && col >= 0 && col < cols());
00333       return derived().coeffRef(row, col);
00334     }
00335 
00336     EIGEN_STRONG_INLINE Scalar&
00337     coeffRefByOuterInner(Index outer, Index inner)
00338     {
00339       return coeffRef(rowIndexByOuterInner(outer, inner),
00340                       colIndexByOuterInner(outer, inner));
00341     }
00342 
00348     EIGEN_STRONG_INLINE Scalar&
00349     operator()(Index row, Index col)
00350     {
00351       eigen_assert(row >= 0 && row < rows()
00352           && col >= 0 && col < cols());
00353       return derived().coeffRef(row, col);
00354     }
00355 
00356 
00372     EIGEN_STRONG_INLINE Scalar&
00373     coeffRef(Index index)
00374     {
00375       eigen_internal_assert(index >= 0 && index < size());
00376       return derived().coeffRef(index);
00377     }
00378 
00386     EIGEN_STRONG_INLINE Scalar&
00387     operator[](Index index)
00388     {
00389       #ifndef EIGEN2_SUPPORT
00390       EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
00391                           THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
00392       #endif
00393       eigen_assert(index >= 0 && index < size());
00394       return derived().coeffRef(index);
00395     }
00396 
00406     EIGEN_STRONG_INLINE Scalar&
00407     operator()(Index index)
00408     {
00409       eigen_assert(index >= 0 && index < size());
00410       return derived().coeffRef(index);
00411     }
00412 
00415     EIGEN_STRONG_INLINE Scalar&
00416     x() { return (*this)[0]; }
00417 
00420     EIGEN_STRONG_INLINE Scalar&
00421     y() { return (*this)[1]; }
00422 
00425     EIGEN_STRONG_INLINE Scalar&
00426     z() { return (*this)[2]; }
00427 
00430     EIGEN_STRONG_INLINE Scalar&
00431     w() { return (*this)[3]; }
00432 
00443     template<int StoreMode>
00444     EIGEN_STRONG_INLINE void writePacket
00445     (Index row, Index col, const typename internal::packet_traits<Scalar>::type& x)
00446     {
00447       eigen_internal_assert(row >= 0 && row < rows()
00448                         && col >= 0 && col < cols());
00449       derived().template writePacket<StoreMode>(row,col,x);
00450     }
00451 
00452 
00454     template<int StoreMode>
00455     EIGEN_STRONG_INLINE void writePacketByOuterInner
00456     (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x)
00457     {
00458       writePacket<StoreMode>(rowIndexByOuterInner(outer, inner),
00459                             colIndexByOuterInner(outer, inner),
00460                             x);
00461     }
00462 
00472     template<int StoreMode>
00473     EIGEN_STRONG_INLINE void writePacket
00474     (Index index, const typename internal::packet_traits<Scalar>::type& x)
00475     {
00476       eigen_internal_assert(index >= 0 && index < size());
00477       derived().template writePacket<StoreMode>(index,x);
00478     }
00479 
00480 #ifndef EIGEN_PARSED_BY_DOXYGEN
00481 
00490     template<typename OtherDerived>
00491     EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
00492     {
00493       eigen_internal_assert(row >= 0 && row < rows()
00494                         && col >= 0 && col < cols());
00495       derived().coeffRef(row, col) = other.derived().coeff(row, col);
00496     }
00497 
00506     template<typename OtherDerived>
00507     EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
00508     {
00509       eigen_internal_assert(index >= 0 && index < size());
00510       derived().coeffRef(index) = other.derived().coeff(index);
00511     }
00512 
00513 
00514     template<typename OtherDerived>
00515     EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
00516     {
00517       const Index row = rowIndexByOuterInner(outer,inner);
00518       const Index col = colIndexByOuterInner(outer,inner);
00519       // derived() is important here: copyCoeff() may be reimplemented in Derived!
00520       derived().copyCoeff(row, col, other);
00521     }
00522 
00531     template<typename OtherDerived, int StoreMode, int LoadMode>
00532     EIGEN_STRONG_INLINE void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
00533     {
00534       eigen_internal_assert(row >= 0 && row < rows()
00535                         && col >= 0 && col < cols());
00536       derived().template writePacket<StoreMode>(row, col,
00537         other.derived().template packet<LoadMode>(row, col));
00538     }
00539 
00548     template<typename OtherDerived, int StoreMode, int LoadMode>
00549     EIGEN_STRONG_INLINE void copyPacket(Index index, const DenseBase<OtherDerived>& other)
00550     {
00551       eigen_internal_assert(index >= 0 && index < size());
00552       derived().template writePacket<StoreMode>(index,
00553         other.derived().template packet<LoadMode>(index));
00554     }
00555 
00557     template<typename OtherDerived, int StoreMode, int LoadMode>
00558     EIGEN_STRONG_INLINE void copyPacketByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
00559     {
00560       const Index row = rowIndexByOuterInner(outer,inner);
00561       const Index col = colIndexByOuterInner(outer,inner);
00562       // derived() is important here: copyCoeff() may be reimplemented in Derived!
00563       derived().template copyPacket< OtherDerived, StoreMode, LoadMode>(row, col, other);
00564     }
00565 #endif
00566 
00567 };
00568 
00580 template<typename Derived>
00581 class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
00582 {
00583   public:
00584 
00585     typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base;
00586     typedef typename internal::traits<Derived>::Index Index;
00587     typedef typename internal::traits<Derived>::Scalar Scalar;
00588     typedef typename NumTraits<Scalar>::Real RealScalar;
00589 
00590     using Base::rows;
00591     using Base::cols;
00592     using Base::size;
00593     using Base::derived;
00594 
00599     inline Index innerStride() const
00600     {
00601       return derived().innerStride();
00602     }
00603 
00609     inline Index outerStride() const
00610     {
00611       return derived().outerStride();
00612     }
00613 
00614     // FIXME shall we remove it ?
00615     inline Index stride() const
00616     {
00617       return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
00618     }
00619 
00624     inline Index rowStride() const
00625     {
00626       return Derived::IsRowMajor ? outerStride() : innerStride();
00627     }
00628 
00633     inline Index colStride() const
00634     {
00635       return Derived::IsRowMajor ? innerStride() : outerStride();
00636     }
00637 };
00638 
00650 template<typename Derived>
00651 class DenseCoeffsBase<Derived, DirectWriteAccessors>
00652   : public DenseCoeffsBase<Derived, WriteAccessors>
00653 {
00654   public:
00655 
00656     typedef DenseCoeffsBase<Derived, WriteAccessors> Base;
00657     typedef typename internal::traits<Derived>::Index Index;
00658     typedef typename internal::traits<Derived>::Scalar Scalar;
00659     typedef typename NumTraits<Scalar>::Real RealScalar;
00660 
00661     using Base::rows;
00662     using Base::cols;
00663     using Base::size;
00664     using Base::derived;
00665 
00670     inline Index innerStride() const
00671     {
00672       return derived().innerStride();
00673     }
00674 
00680     inline Index outerStride() const
00681     {
00682       return derived().outerStride();
00683     }
00684 
00685     // FIXME shall we remove it ?
00686     inline Index stride() const
00687     {
00688       return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
00689     }
00690 
00695     inline Index rowStride() const
00696     {
00697       return Derived::IsRowMajor ? outerStride() : innerStride();
00698     }
00699 
00704     inline Index colStride() const
00705     {
00706       return Derived::IsRowMajor ? innerStride() : outerStride();
00707     }
00708 };
00709 
00710 namespace internal {
00711 
00712 template<typename Derived, bool JustReturnZero>
00713 struct first_aligned_impl
00714 {
00715   static inline typename Derived::Index run(const Derived&)
00716   { return 0; }
00717 };
00718 
00719 template<typename Derived>
00720 struct first_aligned_impl<Derived, false>
00721 {
00722   static inline typename Derived::Index run(const Derived& m)
00723   {
00724     return internal::first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size());
00725   }
00726 };
00727 
00733 template<typename Derived>
00734 static inline typename Derived::Index first_aligned(const Derived& m)
00735 {
00736   return first_aligned_impl
00737           <Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)>
00738           ::run(m);
00739 }
00740 
00741 template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
00742 struct inner_stride_at_compile_time
00743 {
00744   enum { ret = traits<Derived>::InnerStrideAtCompileTime };
00745 };
00746 
00747 template<typename Derived>
00748 struct inner_stride_at_compile_time<Derived, false>
00749 {
00750   enum { ret = 0 };
00751 };
00752 
00753 template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
00754 struct outer_stride_at_compile_time
00755 {
00756   enum { ret = traits<Derived>::OuterStrideAtCompileTime };
00757 };
00758 
00759 template<typename Derived>
00760 struct outer_stride_at_compile_time<Derived, false>
00761 {
00762   enum { ret = 0 };
00763 };
00764 
00765 } // end namespace internal
00766 
00767 } // end namespace Eigen
00768 
00769 #endif // EIGEN_DENSECOEFFSBASE_H