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.
XprHelper.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_XPRHELPER_H 00012 #define EIGEN_XPRHELPER_H 00013 00014 // just a workaround because GCC seems to not really like empty structs 00015 // FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled 00016 // so currently we simply disable this optimization for gcc 4.3 00017 #if (defined __GNUG__) && !((__GNUC__==4) && (__GNUC_MINOR__==3)) 00018 #define EIGEN_EMPTY_STRUCT_CTOR(X) \ 00019 EIGEN_STRONG_INLINE X() {} \ 00020 EIGEN_STRONG_INLINE X(const X& ) {} 00021 #else 00022 #define EIGEN_EMPTY_STRUCT_CTOR(X) 00023 #endif 00024 00025 namespace Eigen { 00026 00027 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex; 00028 00029 namespace internal { 00030 00031 //classes inheriting no_assignment_operator don't generate a default operator=. 00032 class no_assignment_operator 00033 { 00034 private: 00035 no_assignment_operator& operator=(const no_assignment_operator&); 00036 }; 00037 00038 /** \internal return the index type with the largest number of bits */ 00039 template<typename I1, typename I2> 00040 struct promote_index_type 00041 { 00042 typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type; 00043 }; 00044 00045 /** \internal If the template parameter Value is Dynamic, this class is just a wrapper around a T variable that 00046 * can be accessed using value() and setValue(). 00047 * Otherwise, this class is an empty structure and value() just returns the template parameter Value. 00048 */ 00049 template<typename T, int Value> class variable_if_dynamic 00050 { 00051 public: 00052 EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic) 00053 explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); } 00054 static T value() { return T(Value); } 00055 void setValue(T) {} 00056 }; 00057 00058 template<typename T> class variable_if_dynamic<T, Dynamic> 00059 { 00060 T m_value; 00061 variable_if_dynamic() { assert(false); } 00062 public: 00063 explicit variable_if_dynamic(T value) : m_value(value) {} 00064 T value() const { return m_value; } 00065 void setValue(T value) { m_value = value; } 00066 }; 00067 00068 /** \internal like variable_if_dynamic but for DynamicIndex 00069 */ 00070 template<typename T, int Value> class variable_if_dynamicindex 00071 { 00072 public: 00073 EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex) 00074 explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); } 00075 static T value() { return T(Value); } 00076 void setValue(T) {} 00077 }; 00078 00079 template<typename T> class variable_if_dynamicindex<T, DynamicIndex> 00080 { 00081 T m_value; 00082 variable_if_dynamicindex() { assert(false); } 00083 public: 00084 explicit variable_if_dynamicindex(T value) : m_value(value) {} 00085 T value() const { return m_value; } 00086 void setValue(T value) { m_value = value; } 00087 }; 00088 00089 template<typename T> struct functor_traits 00090 { 00091 enum 00092 { 00093 Cost = 10, 00094 PacketAccess = false, 00095 IsRepeatable = false 00096 }; 00097 }; 00098 00099 template<typename T> struct packet_traits; 00100 00101 template<typename T> struct unpacket_traits 00102 { 00103 typedef T type; 00104 enum {size=1}; 00105 }; 00106 00107 template<typename _Scalar, int _Rows, int _Cols, 00108 int _Options = AutoAlign | 00109 ( (_Rows==1 && _Cols!=1) ? RowMajor 00110 : (_Cols==1 && _Rows!=1) ? ColMajor 00111 : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ), 00112 int _MaxRows = _Rows, 00113 int _MaxCols = _Cols 00114 > class make_proper_matrix_type 00115 { 00116 enum { 00117 IsColVector = _Cols==1 && _Rows!=1, 00118 IsRowVector = _Rows==1 && _Cols!=1, 00119 Options = IsColVector ? (_Options | ColMajor) & ~RowMajor 00120 : IsRowVector ? (_Options | RowMajor) & ~ColMajor 00121 : _Options 00122 }; 00123 public: 00124 typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type; 00125 }; 00126 00127 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> 00128 class compute_matrix_flags 00129 { 00130 enum { 00131 row_major_bit = Options&RowMajor ? RowMajorBit : 0, 00132 is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic, 00133 00134 aligned_bit = 00135 ( 00136 ((Options&DontAlign)==0) 00137 && ( 00138 #if EIGEN_ALIGN_STATICALLY 00139 ((!is_dynamic_size_storage) && (((MaxCols*MaxRows*int(sizeof(Scalar))) % 16) == 0)) 00140 #else 00141 0 00142 #endif 00143 00144 || 00145 00146 #if EIGEN_ALIGN 00147 is_dynamic_size_storage 00148 #else 00149 0 00150 #endif 00151 00152 ) 00153 ) ? AlignedBit : 0, 00154 packet_access_bit = packet_traits<Scalar>::Vectorizable && aligned_bit ? PacketAccessBit : 0 00155 }; 00156 00157 public: 00158 enum { ret = LinearAccessBit | LvalueBit | DirectAccessBit | NestByRefBit | packet_access_bit | row_major_bit | aligned_bit }; 00159 }; 00160 00161 template<int _Rows, int _Cols> struct size_at_compile_time 00162 { 00163 enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols }; 00164 }; 00165 00166 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type, 00167 * whereas eval is a const reference in the case of a matrix 00168 */ 00169 00170 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type; 00171 template<typename T, typename BaseClassType> struct plain_matrix_type_dense; 00172 template<typename T> struct plain_matrix_type<T,Dense> 00173 { 00174 typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind>::type type; 00175 }; 00176 00177 template<typename T> struct plain_matrix_type_dense<T,MatrixXpr> 00178 { 00179 typedef Matrix<typename traits<T>::Scalar, 00180 traits<T>::RowsAtCompileTime, 00181 traits<T>::ColsAtCompileTime, 00182 AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor), 00183 traits<T>::MaxRowsAtCompileTime, 00184 traits<T>::MaxColsAtCompileTime 00185 > type; 00186 }; 00187 00188 template<typename T> struct plain_matrix_type_dense<T,ArrayXpr> 00189 { 00190 typedef Array<typename traits<T>::Scalar, 00191 traits<T>::RowsAtCompileTime, 00192 traits<T>::ColsAtCompileTime, 00193 AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor), 00194 traits<T>::MaxRowsAtCompileTime, 00195 traits<T>::MaxColsAtCompileTime 00196 > type; 00197 }; 00198 00199 /* eval : the return type of eval(). For matrices, this is just a const reference 00200 * in order to avoid a useless copy 00201 */ 00202 00203 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval; 00204 00205 template<typename T> struct eval<T,Dense> 00206 { 00207 typedef typename plain_matrix_type<T>::type type; 00208 // typedef typename T::PlainObject type; 00209 // typedef T::Matrix<typename traits<T>::Scalar, 00210 // traits<T>::RowsAtCompileTime, 00211 // traits<T>::ColsAtCompileTime, 00212 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor), 00213 // traits<T>::MaxRowsAtCompileTime, 00214 // traits<T>::MaxColsAtCompileTime 00215 // > type; 00216 }; 00217 00218 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy 00219 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 00220 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense> 00221 { 00222 typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; 00223 }; 00224 00225 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 00226 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense> 00227 { 00228 typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; 00229 }; 00230 00231 00232 00233 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major 00234 */ 00235 template<typename T> struct plain_matrix_type_column_major 00236 { 00237 enum { Rows = traits<T>::RowsAtCompileTime, 00238 Cols = traits<T>::ColsAtCompileTime, 00239 MaxRows = traits<T>::MaxRowsAtCompileTime, 00240 MaxCols = traits<T>::MaxColsAtCompileTime 00241 }; 00242 typedef Matrix<typename traits<T>::Scalar, 00243 Rows, 00244 Cols, 00245 (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor, 00246 MaxRows, 00247 MaxCols 00248 > type; 00249 }; 00250 00251 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major 00252 */ 00253 template<typename T> struct plain_matrix_type_row_major 00254 { 00255 enum { Rows = traits<T>::RowsAtCompileTime, 00256 Cols = traits<T>::ColsAtCompileTime, 00257 MaxRows = traits<T>::MaxRowsAtCompileTime, 00258 MaxCols = traits<T>::MaxColsAtCompileTime 00259 }; 00260 typedef Matrix<typename traits<T>::Scalar, 00261 Rows, 00262 Cols, 00263 (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor, 00264 MaxRows, 00265 MaxCols 00266 > type; 00267 }; 00268 00269 // we should be able to get rid of this one too 00270 template<typename T> struct must_nest_by_value { enum { ret = false }; }; 00271 00272 /** \internal The reference selector for template expressions. The idea is that we don't 00273 * need to use references for expressions since they are light weight proxy 00274 * objects which should generate no copying overhead. */ 00275 template <typename T> 00276 struct ref_selector 00277 { 00278 typedef typename conditional< 00279 bool(traits<T>::Flags & NestByRefBit), 00280 T const&, 00281 const T 00282 >::type type; 00283 }; 00284 00285 /** \internal Adds the const qualifier on the value-type of T2 if and only if T1 is a const type */ 00286 template<typename T1, typename T2> 00287 struct transfer_constness 00288 { 00289 typedef typename conditional< 00290 bool(internal::is_const<T1>::value), 00291 typename internal::add_const_on_value_type<T2>::type, 00292 T2 00293 >::type type; 00294 }; 00295 00296 /** \internal Determines how a given expression should be nested into another one. 00297 * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be 00298 * nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or 00299 * evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is 00300 * a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes 00301 * many coefficient accesses in the nested expressions -- as is the case with matrix product for example. 00302 * 00303 * \param T the type of the expression being nested 00304 * \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression. 00305 * 00306 * Note that if no evaluation occur, then the constness of T is preserved. 00307 * 00308 * Example. Suppose that a, b, and c are of type Matrix3d. The user forms the expression a*(b+c). 00309 * b+c is an expression "sum of matrices", which we will denote by S. In order to determine how to nest it, 00310 * the Product expression uses: nested<S, 3>::ret, which turns out to be Matrix3d because the internal logic of 00311 * nested determined that in this case it was better to evaluate the expression b+c into a temporary. On the other hand, 00312 * since a is of type Matrix3d, the Product expression nests it as nested<Matrix3d, 3>::ret, which turns out to be 00313 * const Matrix3d&, because the internal logic of nested determined that since a was already a matrix, there was no point 00314 * in copying it into another matrix. 00315 */ 00316 template<typename T, int n=1, typename PlainObject = typename eval<T>::type> struct nested 00317 { 00318 enum { 00319 // for the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values. 00320 // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values. 00321 // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues 00322 // (poor choice of temporaries). 00323 // it's important that this value can still be squared without integer overflowing. 00324 DynamicAsInteger = 10000, 00325 ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost, 00326 ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost), 00327 CoeffReadCost = traits<T>::CoeffReadCost, 00328 CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost), 00329 NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n, 00330 CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger, 00331 CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger 00332 }; 00333 00334 typedef typename conditional< 00335 ( (int(traits<T>::Flags) & EvalBeforeNestingBit) || 00336 int(CostEvalAsInteger) < int(CostNoEvalAsInteger) 00337 ), 00338 PlainObject, 00339 typename ref_selector<T>::type 00340 >::type type; 00341 }; 00342 00343 template<typename T> 00344 inline T* const_cast_ptr(const T* ptr) 00345 { 00346 return const_cast<T*>(ptr); 00347 } 00348 00349 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind> 00350 struct dense_xpr_base 00351 { 00352 /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */ 00353 }; 00354 00355 template<typename Derived> 00356 struct dense_xpr_base<Derived, MatrixXpr> 00357 { 00358 typedef MatrixBase<Derived> type; 00359 }; 00360 00361 template<typename Derived> 00362 struct dense_xpr_base<Derived, ArrayXpr> 00363 { 00364 typedef ArrayBase<Derived> type; 00365 }; 00366 00367 /** \internal Helper base class to add a scalar multiple operator 00368 * overloads for complex types */ 00369 template<typename Derived, typename Scalar, typename OtherScalar, typename BaseType, 00370 bool EnableIt = !is_same<Scalar,OtherScalar>::value > 00371 struct special_scalar_op_base : public BaseType 00372 { 00373 // dummy operator* so that the 00374 // "using special_scalar_op_base::operator*" compiles 00375 void operator* () const; 00376 }; 00377 00378 template<typename Derived,typename Scalar,typename OtherScalar, typename BaseType> 00379 struct special_scalar_op_base<Derived,Scalar,OtherScalar,BaseType,true> : public BaseType 00380 { 00381 const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> 00382 operator* (const OtherScalar& scalar) const 00383 { 00384 return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> 00385 (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar)); 00386 } 00387 00388 inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> 00389 operator* (const OtherScalar& scalar, const Derived& matrix) 00390 { return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); } 00391 }; 00392 00393 template<typename XprType, typename CastType> struct cast_return_type 00394 { 00395 typedef typename XprType::Scalar CurrentScalarType; 00396 typedef typename remove_all<CastType>::type _CastType; 00397 typedef typename _CastType::Scalar NewScalarType; 00398 typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value, 00399 const XprType&,CastType>::type type; 00400 }; 00401 00402 template <typename A, typename B> struct promote_storage_type; 00403 00404 template <typename A> struct promote_storage_type<A,A> 00405 { 00406 typedef A ret; 00407 }; 00408 00409 /** \internal gives the plain matrix or array type to store a row/column/diagonal of a matrix type. 00410 * \param Scalar optional parameter allowing to pass a different scalar type than the one of the MatrixType. 00411 */ 00412 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00413 struct plain_row_type 00414 { 00415 typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime, 00416 ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType; 00417 typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime, 00418 ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType; 00419 00420 typedef typename conditional< 00421 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00422 MatrixRowType, 00423 ArrayRowType 00424 >::type type; 00425 }; 00426 00427 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00428 struct plain_col_type 00429 { 00430 typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1, 00431 ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType; 00432 typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1, 00433 ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType; 00434 00435 typedef typename conditional< 00436 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00437 MatrixColType, 00438 ArrayColType 00439 >::type type; 00440 }; 00441 00442 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00443 struct plain_diag_type 00444 { 00445 enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime), 00446 max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime) 00447 }; 00448 typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType; 00449 typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType; 00450 00451 typedef typename conditional< 00452 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00453 MatrixDiagType, 00454 ArrayDiagType 00455 >::type type; 00456 }; 00457 00458 template<typename ExpressionType> 00459 struct is_lvalue 00460 { 00461 enum { value = !bool(is_const<ExpressionType>::value) && 00462 bool(traits<ExpressionType>::Flags & LvalueBit) }; 00463 }; 00464 00465 } // end namespace internal 00466 00467 } // end namespace Eigen 00468 00469 #endif // EIGEN_XPRHELPER_H
Generated on Thu Nov 17 2022 22:01:31 by
1.7.2