Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Thu Nov 17 2022 22:01:30 by
1.7.2