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 ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value, 112 MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch 113 }; 114 typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; 115 }; 116 117 }; 118 119 template<typename Derived> 120 struct traits<RefBase<Derived> > : public traits<Derived> {}; 121 122 } 123 124 template<typename Derived> class RefBase 125 : public MapBase<Derived> 126 { 127 typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType; 128 typedef typename internal::traits<Derived>::StrideType StrideType; 129 130 public: 131 132 typedef MapBase<Derived> Base; 133 EIGEN_DENSE_PUBLIC_INTERFACE(RefBase) 134 135 inline Index innerStride() const 136 { 137 return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; 138 } 139 140 inline Index outerStride() const 141 { 142 return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() 143 : IsVectorAtCompileTime ? this->size() 144 : int(Flags)&RowMajorBit ? this->cols() 145 : this->rows(); 146 } 147 148 RefBase() 149 : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime), 150 // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values: 151 m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime, 152 StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime) 153 {} 154 155 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase) 156 157 protected: 158 159 typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase; 160 161 template<typename Expression> 162 void construct(Expression& expr) 163 { 164 if(PlainObjectType::RowsAtCompileTime==1) 165 { 166 eigen_assert(expr.rows()==1 || expr.cols()==1); 167 ::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size()); 168 } 169 else if(PlainObjectType::ColsAtCompileTime==1) 170 { 171 eigen_assert(expr.rows()==1 || expr.cols()==1); 172 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1); 173 } 174 else 175 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols()); 176 177 if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit))) 178 ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1); 179 else 180 ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(), 181 StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride()); 182 } 183 184 StrideBase m_stride; 185 }; 186 187 188 template<typename PlainObjectType, int Options, typename StrideType> class Ref 189 : public RefBase<Ref<PlainObjectType, Options, StrideType> > 190 { 191 private: 192 typedef internal::traits<Ref> Traits; 193 template<typename Derived> 194 inline Ref(const PlainObjectBase<Derived>& expr, 195 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0); 196 public: 197 198 typedef RefBase<Ref> Base; 199 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 200 201 202 #ifndef EIGEN_PARSED_BY_DOXYGEN 203 template<typename Derived> 204 inline Ref(PlainObjectBase<Derived>& expr, 205 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0) 206 { 207 EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 208 Base::construct(expr.derived()); 209 } 210 template<typename Derived> 211 inline Ref(const DenseBase<Derived>& expr, 212 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0) 213 #else 214 template<typename Derived> 215 inline Ref(DenseBase<Derived>& expr) 216 #endif 217 { 218 EIGEN_STATIC_ASSERT(static_cast<bool>(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 219 EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 220 enum { THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY = Derived::ThisConstantIsPrivateInPlainObjectBase}; 221 Base::construct(expr.const_cast_derived()); 222 } 223 224 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref) 225 226 }; 227 228 // this is the const ref version 229 template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType> 230 : public RefBase<Ref<const TPlainObjectType, Options, StrideType> > 231 { 232 typedef internal::traits<Ref> Traits; 233 public: 234 235 typedef RefBase<Ref> Base; 236 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 237 238 template<typename Derived> 239 inline Ref(const DenseBase<Derived>& expr, 240 typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0) 241 { 242 // std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n"; 243 // std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n"; 244 // std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n"; 245 construct(expr.derived(), typename Traits::template match<Derived>::type()); 246 } 247 248 protected: 249 250 template<typename Expression> 251 void construct(const Expression& expr,internal::true_type) 252 { 253 Base::construct(expr); 254 } 255 256 template<typename Expression> 257 void construct(const Expression& expr, internal::false_type) 258 { 259 m_object.lazyAssign(expr); 260 Base::construct(m_object); 261 } 262 263 protected: 264 TPlainObjectType m_object; 265 }; 266 267 } // end namespace Eigen 268 269 #endif // EIGEN_REF_H 270