1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_REF_H 11 #define EIGEN_REF_H 12 13 namespace Eigen { 14 15 template<typename Derived> class RefBase; 16 template<typename PlainObjectType, int Options = 0, 17 typename StrideType = typename internal::conditional<PlainObjectType::IsVectorAtCompileTime,InnerStride<1>,OuterStride<> >::type > class Ref; 18 19 /** \class Ref 20 * \ingroup Core_Module 21 * 22 * \brief A matrix or vector expression mapping an existing expressions 23 * 24 * \tparam PlainObjectType the equivalent matrix type of the mapped data 25 * \tparam Options specifies whether the pointer is \c #Aligned, or \c #Unaligned. 26 * The default is \c #Unaligned. 27 * \tparam StrideType optionally specifies strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1), 28 * but accept a variable outer stride (leading dimension). 29 * This can be overridden by specifying strides. 30 * The type passed here must be a specialization of the Stride template, see examples below. 31 * 32 * This class permits to write non template functions taking Eigen's object as parameters while limiting the number of copies. 33 * A Ref<> object can represent either a const expression or a l-value: 34 * \code 35 * // in-out argument: 36 * void foo1(Ref<VectorXf> x); 37 * 38 * // read-only const argument: 39 * void foo2(const Ref<const VectorXf>& x); 40 * \endcode 41 * 42 * In the in-out case, the input argument must satisfies the constraints of the actual Ref<> type, otherwise a compilation issue will be triggered. 43 * By default, a Ref<VectorXf> can reference any dense vector expression of float having a contiguous memory layout. 44 * Likewise, a Ref<MatrixXf> can reference any column major dense matrix expression of float whose column's elements are contiguously stored with 45 * 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), 46 * can be greater than the number of rows. 47 * 48 * 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. 49 * Here are some examples: 50 * \code 51 * MatrixXf A; 52 * VectorXf a; 53 * foo1(a.head()); // OK 54 * foo1(A.col()); // OK 55 * foo1(A.row()); // compilation error because here innerstride!=1 56 * foo2(A.row()); // The row is copied into a contiguous temporary 57 * foo2(2*a); // The expression is evaluated into a temporary 58 * foo2(A.col().segment(2,4)); // No temporary 59 * \endcode 60 * 61 * The range of inputs that can be referenced without temporary can be enlarged using the last two template parameter. 62 * Here is an example accepting an innerstride!=1: 63 * \code 64 * // in-out argument: 65 * void foo3(Ref<VectorXf,0,InnerStride<> > x); 66 * foo3(A.row()); // OK 67 * \endcode 68 * 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 69 * expensive address computations even if the input is contiguously stored in memory. To overcome this issue, one might propose to overloads internally calling a 70 * template function, e.g.: 71 * \code 72 * // in the .h: 73 * void foo(const Ref<MatrixXf>& A); 74 * void foo(const Ref<MatrixXf,0,Stride<> >& A); 75 * 76 * // in the .cpp: 77 * template<typename TypeOfA> void foo_impl(const TypeOfA& A) { 78 * ... // crazy code goes here 79 * } 80 * void foo(const Ref<MatrixXf>& A) { foo_impl(A); } 81 * void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); } 82 * \endcode 83 * 84 * 85 * \sa PlainObjectBase::Map(), \ref TopicStorageOrders 86 */ 87 88 namespace internal { 89 90 template<typename _PlainObjectType, int _Options, typename _StrideType> 91 struct traits<Ref<_PlainObjectType, _Options, _StrideType> > 92 : public traits<Map<_PlainObjectType, _Options, _StrideType> > 93 { 94 typedef _PlainObjectType PlainObjectType; 95 typedef _StrideType StrideType; 96 enum { 97 Options = _Options, 98 Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit 99 }; 100 101 template<typename Derived> struct match { 102 enum { 103 HasDirectAccess = internal::has_direct_access<Derived>::ret, 104 StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), 105 InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic) 106 || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime) 107 || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), 108 OuterStrideMatch = Derived::IsVectorAtCompileTime 109 || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime), 110 AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit), 111 MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch 112 }; 113 typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; 114 }; 115 116 }; 117 118 template<typename Derived> 119 struct traits<RefBase<Derived> > : public traits<Derived> {}; 120 121 } 122 123 template<typename Derived> class RefBase 124 : public MapBase<Derived> 125 { 126 typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType; 127 typedef typename internal::traits<Derived>::StrideType StrideType; 128 129 public: 130 131 typedef MapBase<Derived> Base; 132 EIGEN_DENSE_PUBLIC_INTERFACE(RefBase) 133 134 inline Index innerStride() const 135 { 136 return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; 137 } 138 139 inline Index outerStride() const 140 { 141 return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() 142 : IsVectorAtCompileTime ? this->size() 143 : int(Flags)&RowMajorBit ? this->cols() 144 : this->rows(); 145 } 146 147 RefBase() 148 : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime), 149 // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values: 150 m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime, 151 StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime) 152 {} 153 154 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase) 155 156 protected: 157 158 typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase; 159 160 template<typename Expression> 161 void construct(Expression& expr) 162 { 163 if(PlainObjectType::RowsAtCompileTime==1) 164 { 165 eigen_assert(expr.rows()==1 || expr.cols()==1); 166 ::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size()); 167 } 168 else if(PlainObjectType::ColsAtCompileTime==1) 169 { 170 eigen_assert(expr.rows()==1 || expr.cols()==1); 171 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1); 172 } 173 else 174 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols()); 175 176 if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit))) 177 ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1); 178 else 179 ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(), 180 StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride()); 181 } 182 183 StrideBase m_stride; 184 }; 185 186 187 template<typename PlainObjectType, int Options, typename StrideType> class Ref 188 : public RefBase<Ref<PlainObjectType, Options, StrideType> > 189 { 190 typedef internal::traits<Ref> Traits; 191 template<typename Derived> 192 inline Ref(const PlainObjectBase<Derived>& expr); 193 public: 194 195 typedef RefBase<Ref> Base; 196 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 197 198 199 #ifndef EIGEN_PARSED_BY_DOXYGEN 200 template<typename Derived> 201 inline Ref(PlainObjectBase<Derived>& expr) 202 { 203 EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 204 Base::construct(expr.derived()); 205 } 206 template<typename Derived> 207 inline Ref(const DenseBase<Derived>& expr) 208 #else 209 template<typename Derived> 210 inline Ref(DenseBase<Derived>& expr) 211 #endif 212 { 213 EIGEN_STATIC_ASSERT(static_cast<bool>(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 214 EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 215 enum { THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY = Derived::ThisConstantIsPrivateInPlainObjectBase}; 216 Base::construct(expr.const_cast_derived()); 217 } 218 219 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref) 220 221 }; 222 223 // this is the const ref version 224 template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType> 225 : public RefBase<Ref<const TPlainObjectType, Options, StrideType> > 226 { 227 typedef internal::traits<Ref> Traits; 228 public: 229 230 typedef RefBase<Ref> Base; 231 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 232 233 template<typename Derived> 234 inline Ref(const DenseBase<Derived>& expr) 235 { 236 // std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n"; 237 // std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n"; 238 // std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n"; 239 construct(expr.derived(), typename Traits::template match<Derived>::type()); 240 } 241 242 protected: 243 244 template<typename Expression> 245 void construct(const Expression& expr,internal::true_type) 246 { 247 Base::construct(expr); 248 } 249 250 template<typename Expression> 251 void construct(const Expression& expr, internal::false_type) 252 { 253 m_object.lazyAssign(expr); 254 Base::construct(m_object); 255 } 256 257 protected: 258 TPlainObjectType m_object; 259 }; 260 261 } // end namespace Eigen 262 263 #endif // EIGEN_REF_H 264