Eigne Matrix Class Library

Dependents:   Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Ref.h Source File

Ref.h

00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_REF_H
00011 #define EIGEN_REF_H
00012 
00013 namespace Eigen { 
00014 
00015 template<typename Derived> class RefBase;
00016 template<typename PlainObjectType, int Options = 0,
00017          typename StrideType = typename internal::conditional<PlainObjectType::IsVectorAtCompileTime,InnerStride<1>,OuterStride<> >::type > class Ref;
00018 
00019 /** \class Ref
00020   * \ingroup Core_Module
00021   *
00022   * \brief A matrix or vector expression mapping an existing expressions
00023   *
00024   * \tparam PlainObjectType the equivalent matrix type of the mapped data
00025   * \tparam Options specifies whether the pointer is \c #Aligned, or \c #Unaligned.
00026   *                The default is \c #Unaligned.
00027   * \tparam StrideType optionally specifies strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1),
00028   *                   but accept a variable outer stride (leading dimension).
00029   *                   This can be overridden by specifying strides.
00030   *                   The type passed here must be a specialization of the Stride template, see examples below.
00031   *
00032   * This class permits to write non template functions taking Eigen's object as parameters while limiting the number of copies.
00033   * A Ref<> object can represent either a const expression or a l-value:
00034   * \code
00035   * // in-out argument:
00036   * void foo1(Ref<VectorXf> x);
00037   *
00038   * // read-only const argument:
00039   * void foo2(const Ref<const VectorXf>& x);
00040   * \endcode
00041   *
00042   * In the in-out case, the input argument must satisfies the constraints of the actual Ref<> type, otherwise a compilation issue will be triggered.
00043   * By default, a Ref<VectorXf> can reference any dense vector expression of float having a contiguous memory layout.
00044   * Likewise, a Ref<MatrixXf> can reference any column major dense matrix expression of float whose column's elements are contiguously stored with
00045   * the possibility to have a constant space inbetween each column, i.e.: the inner stride mmust be equal to 1, but the outer-stride (or leading dimension),
00046   * can be greater than the number of rows.
00047   *
00048   * In the const case, if the input expression does not match the above requirement, then it is evaluated into a temporary before being passed to the function.
00049   * Here are some examples:
00050   * \code
00051   * MatrixXf A;
00052   * VectorXf a;
00053   * foo1(a.head());             // OK
00054   * foo1(A.col());              // OK
00055   * foo1(A.row());              // compilation error because here innerstride!=1
00056   * foo2(A.row());              // The row is copied into a contiguous temporary
00057   * foo2(2*a);                  // The expression is evaluated into a temporary
00058   * foo2(A.col().segment(2,4)); // No temporary
00059   * \endcode
00060   *
00061   * The range of inputs that can be referenced without temporary can be enlarged using the last two template parameter.
00062   * Here is an example accepting an innerstride!=1:
00063   * \code
00064   * // in-out argument:
00065   * void foo3(Ref<VectorXf,0,InnerStride<> > x);
00066   * foo3(A.row());              // OK
00067   * \endcode
00068   * The downside here is that the function foo3 might be significantly slower than foo1 because it won't be able to exploit vectorization, and will involved more
00069   * expensive address computations even if the input is contiguously stored in memory. To overcome this issue, one might propose to overloads internally calling a
00070   * template function, e.g.:
00071   * \code
00072   * // in the .h:
00073   * void foo(const Ref<MatrixXf>& A);
00074   * void foo(const Ref<MatrixXf,0,Stride<> >& A);
00075   *
00076   * // in the .cpp:
00077   * template<typename TypeOfA> void foo_impl(const TypeOfA& A) {
00078   *     ... // crazy code goes here
00079   * }
00080   * void foo(const Ref<MatrixXf>& A) { foo_impl(A); }
00081   * void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); }
00082   * \endcode
00083   *
00084   *
00085   * \sa PlainObjectBase::Map(), \ref TopicStorageOrders
00086   */
00087 
00088 namespace internal {
00089 
00090 template<typename _PlainObjectType, int _Options, typename _StrideType>
00091 struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
00092   : public traits<Map<_PlainObjectType, _Options, _StrideType> >
00093 {
00094   typedef _PlainObjectType PlainObjectType;
00095   typedef _StrideType StrideType;
00096   enum {
00097     Options = _Options,
00098     Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit
00099   };
00100 
00101   template<typename Derived> struct match {
00102     enum {
00103       HasDirectAccess = internal::has_direct_access<Derived>::ret,
00104       StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
00105       InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
00106                       || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
00107                       || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
00108       OuterStrideMatch = Derived::IsVectorAtCompileTime
00109                       || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
00110       AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
00111       ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
00112       MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
00113     };
00114     typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
00115   };
00116   
00117 };
00118 
00119 template<typename Derived>
00120 struct traits<RefBase<Derived> > : public traits<Derived> {};
00121 
00122 }
00123 
00124 template<typename Derived> class RefBase
00125  : public MapBase<Derived>
00126 {
00127   typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType;
00128   typedef typename internal::traits<Derived>::StrideType StrideType;
00129 
00130 public:
00131 
00132   typedef MapBase<Derived>  Base;
00133   EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
00134 
00135   inline Index innerStride() const
00136   {
00137     return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
00138   }
00139 
00140   inline Index outerStride() const
00141   {
00142     return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
00143          : IsVectorAtCompileTime ? this->size()
00144          : int(Flags)&RowMajorBit ? this->cols()
00145          : this->rows();
00146   }
00147 
00148   RefBase()
00149     : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime),
00150       // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values:
00151       m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime,
00152                StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime)
00153   {}
00154   
00155   EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase)
00156 
00157 protected:
00158 
00159   typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase;
00160 
00161   template<typename Expression>
00162   void construct(Expression& expr)
00163   {
00164     if(PlainObjectType::RowsAtCompileTime==1)
00165     {
00166       eigen_assert(expr.rows()==1 || expr.cols()==1);
00167       ::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size());
00168     }
00169     else if(PlainObjectType::ColsAtCompileTime==1)
00170     {
00171       eigen_assert(expr.rows()==1 || expr.cols()==1);
00172       ::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1);
00173     }
00174     else
00175       ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
00176     
00177     if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit)))
00178       ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1);
00179     else
00180       ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
00181                                    StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());    
00182   }
00183 
00184   StrideBase m_stride;
00185 };
00186 
00187 
00188 template<typename PlainObjectType, int Options, typename StrideType> class Ref
00189   : public RefBase<Ref<PlainObjectType, Options, StrideType> >
00190 {
00191   private:
00192     typedef internal::traits<Ref> Traits;
00193     template<typename Derived>
00194     inline Ref(const PlainObjectBase<Derived>& expr,
00195                typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0);
00196   public:
00197 
00198     typedef RefBase<Ref> Base ;
00199     EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
00200 
00201 
00202     #ifndef EIGEN_PARSED_BY_DOXYGEN
00203     template<typename Derived>
00204     inline Ref(PlainObjectBase<Derived>& expr,
00205                typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
00206     {
00207       EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
00208       Base::construct(expr.derived());
00209     }
00210     template<typename Derived>
00211     inline Ref(const DenseBase<Derived> & expr,
00212                typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
00213     #else
00214     template<typename Derived>
00215     inline Ref(DenseBase<Derived> & expr)
00216     #endif
00217     {
00218       EIGEN_STATIC_ASSERT(static_cast<bool>(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
00219       EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
00220       enum { THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY = Derived::ThisConstantIsPrivateInPlainObjectBase};
00221       Base::construct(expr.const_cast_derived());
00222     }
00223 
00224     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
00225 
00226 };
00227 
00228 // this is the const ref version
00229 template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType>
00230   : public RefBase<Ref<const TPlainObjectType, Options, StrideType> >
00231 {
00232     typedef internal::traits<Ref> Traits;
00233   public:
00234 
00235     typedef RefBase<Ref> Base;
00236     EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
00237 
00238     template<typename Derived>
00239     inline Ref(const DenseBase<Derived>& expr,
00240                typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0)
00241     {
00242 //      std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
00243 //      std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
00244 //      std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
00245       construct(expr.derived(), typename Traits::template match<Derived>::type());
00246     }
00247     
00248     inline Ref(const Ref& other) : Base(other) {
00249       // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
00250     }
00251 
00252     template<typename OtherRef>
00253     inline Ref(const RefBase<OtherRef>& other) {
00254       construct(other.derived(), typename Traits::template match<OtherRef>::type());
00255     }
00256 
00257   protected:
00258 
00259     template<typename Expression>
00260     void construct(const Expression& expr,internal::true_type)
00261     {
00262       Base::construct(expr);
00263     }
00264 
00265     template<typename Expression>
00266     void construct(const Expression& expr, internal::false_type)
00267     {
00268       m_object.lazyAssign(expr);
00269       Base::construct(m_object);
00270     }
00271 
00272   protected:
00273     TPlainObjectType m_object;
00274 };
00275 
00276 } // end namespace Eigen
00277 
00278 #endif // EIGEN_REF_H