![]() |
Eigen
3.3.3
|
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 namespace internal { 00016 00017 template<typename _PlainObjectType, int _Options, typename _StrideType> 00018 struct traits<Ref<_PlainObjectType, _Options, _StrideType> > 00019 : public traits<Map<_PlainObjectType, _Options, _StrideType> > 00020 { 00021 typedef _PlainObjectType PlainObjectType; 00022 typedef _StrideType StrideType; 00023 enum { 00024 Options = _Options, 00025 Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit, 00026 Alignment = traits<Map<_PlainObjectType, _Options, _StrideType> >::Alignment 00027 }; 00028 00029 template<typename Derived> struct match { 00030 enum { 00031 HasDirectAccess = internal::has_direct_access<Derived>::ret, 00032 StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), 00033 InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic) 00034 || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime) 00035 || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), 00036 OuterStrideMatch = Derived::IsVectorAtCompileTime 00037 || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime), 00038 // NOTE, this indirection of evaluator<Derived>::Alignment is needed 00039 // to workaround a very strange bug in MSVC related to the instantiation 00040 // of has_*ary_operator in evaluator<CwiseNullaryOp>. 00041 // This line is surprisingly very sensitive. For instance, simply adding parenthesis 00042 // as "DerivedAlignment = (int(evaluator<Derived>::Alignment))," will make MSVC fail... 00043 DerivedAlignment = int(evaluator<Derived>::Alignment), 00044 AlignmentMatch = (int(traits<PlainObjectType>::Alignment)==int(Unaligned)) || (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment 00045 ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value, 00046 MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch 00047 }; 00048 typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; 00049 }; 00050 00051 }; 00052 00053 template<typename Derived> 00054 struct traits<RefBase<Derived> > : public traits<Derived> {}; 00055 00056 } 00057 00058 template<typename Derived> class RefBase 00059 : public MapBase<Derived> 00060 { 00061 typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType; 00062 typedef typename internal::traits<Derived>::StrideType StrideType; 00063 00064 public: 00065 00066 typedef MapBase<Derived> Base; 00067 EIGEN_DENSE_PUBLIC_INTERFACE(RefBase) 00068 00069 EIGEN_DEVICE_FUNC inline Index innerStride() const 00070 { 00071 return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; 00072 } 00073 00074 EIGEN_DEVICE_FUNC inline Index outerStride() const 00075 { 00076 return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() 00077 : IsVectorAtCompileTime ? this->size() 00078 : int(Flags)&RowMajorBit ? this->cols() 00079 : this->rows(); 00080 } 00081 00082 EIGEN_DEVICE_FUNC RefBase() 00083 : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime), 00084 // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values: 00085 m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime, 00086 StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime) 00087 {} 00088 00089 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase) 00090 00091 protected: 00092 00093 typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase; 00094 00095 template<typename Expression> 00096 EIGEN_DEVICE_FUNC void construct(Expression& expr) 00097 { 00098 if(PlainObjectType::RowsAtCompileTime==1) 00099 { 00100 eigen_assert(expr.rows()==1 || expr.cols()==1); 00101 ::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size()); 00102 } 00103 else if(PlainObjectType::ColsAtCompileTime==1) 00104 { 00105 eigen_assert(expr.rows()==1 || expr.cols()==1); 00106 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1); 00107 } 00108 else 00109 ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols()); 00110 00111 if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit))) 00112 ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1); 00113 else 00114 ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(), 00115 StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride()); 00116 } 00117 00118 StrideBase m_stride; 00119 }; 00120 00190 template<typename PlainObjectType, int Options, typename StrideType> class Ref 00191 : public RefBase<Ref<PlainObjectType, Options, StrideType> > 00192 { 00193 private: 00194 typedef internal::traits<Ref> Traits; 00195 template<typename Derived> 00196 EIGEN_DEVICE_FUNC inline Ref(const PlainObjectBase<Derived>& expr, 00197 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0); 00198 public: 00199 00200 typedef RefBase<Ref> Base; 00201 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 00202 00203 00204 #ifndef EIGEN_PARSED_BY_DOXYGEN 00205 template<typename Derived> 00206 EIGEN_DEVICE_FUNC inline Ref(PlainObjectBase<Derived>& expr, 00207 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0) 00208 { 00209 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 00210 Base::construct(expr.derived()); 00211 } 00212 template<typename Derived> 00213 EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr, 00214 typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0) 00215 #else 00216 00217 template<typename Derived> 00218 inline Ref(DenseBase<Derived>& expr) 00219 #endif 00220 { 00221 EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 00222 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 00223 EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase,THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 00224 Base::construct(expr.const_cast_derived()); 00225 } 00226 00227 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref) 00228 00229 }; 00230 00231 // this is the const ref version 00232 template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType> 00233 : public RefBase<Ref<const TPlainObjectType, Options, StrideType> > 00234 { 00235 typedef internal::traits<Ref> Traits; 00236 public: 00237 00238 typedef RefBase<Ref> Base; 00239 EIGEN_DENSE_PUBLIC_INTERFACE(Ref) 00240 00241 template<typename Derived> 00242 EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr, 00243 typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0) 00244 { 00245 // std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n"; 00246 // std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n"; 00247 // std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n"; 00248 construct(expr.derived(), typename Traits::template match<Derived>::type()); 00249 } 00250 00251 EIGEN_DEVICE_FUNC inline Ref(const Ref& other) : Base(other) { 00252 // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy 00253 } 00254 00255 template<typename OtherRef> 00256 EIGEN_DEVICE_FUNC inline Ref(const RefBase<OtherRef>& other) { 00257 construct(other.derived(), typename Traits::template match<OtherRef>::type()); 00258 } 00259 00260 protected: 00261 00262 template<typename Expression> 00263 EIGEN_DEVICE_FUNC void construct(const Expression& expr,internal::true_type) 00264 { 00265 Base::construct(expr); 00266 } 00267 00268 template<typename Expression> 00269 EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::false_type) 00270 { 00271 internal::call_assignment_no_alias(m_object,expr,internal::assign_op<Scalar,Scalar>()); 00272 Base::construct(m_object); 00273 } 00274 00275 protected: 00276 TPlainObjectType m_object; 00277 }; 00278 00279 } // end namespace Eigen 00280 00281 #endif // EIGEN_REF_H