![]() |
Eigen
3.3.3
|
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 EIGEN_COMP_GNUC && !EIGEN_GNUC_AT(4,3) 00018 #define EIGEN_EMPTY_STRUCT_CTOR(X) \ 00019 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X() {} \ 00020 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X(const X& ) {} 00021 #else 00022 #define EIGEN_EMPTY_STRUCT_CTOR(X) 00023 #endif 00024 00025 namespace Eigen { 00026 00027 namespace internal { 00028 00029 template<typename IndexDest, typename IndexSrc> 00030 EIGEN_DEVICE_FUNC 00031 inline IndexDest convert_index(const IndexSrc& idx) { 00032 // for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away: 00033 eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value to big for target type"); 00034 return IndexDest(idx); 00035 } 00036 00037 00038 // promote_scalar_arg is an helper used in operation between an expression and a scalar, like: 00039 // expression * scalar 00040 // Its role is to determine how the type T of the scalar operand should be promoted given the scalar type ExprScalar of the given expression. 00041 // The IsSupported template parameter must be provided by the caller as: internal::has_ReturnType<ScalarBinaryOpTraits<ExprScalar,T,op> >::value using the proper order for ExprScalar and T. 00042 // Then the logic is as follows: 00043 // - if the operation is natively supported as defined by IsSupported, then the scalar type is not promoted, and T is returned. 00044 // - otherwise, NumTraits<ExprScalar>::Literal is returned if T is implicitly convertible to NumTraits<ExprScalar>::Literal AND that this does not imply a float to integer conversion. 00045 // - otherwise, ExprScalar is returned if T is implicitly convertible to ExprScalar AND that this does not imply a float to integer conversion. 00046 // - In all other cases, the promoted type is not defined, and the respective operation is thus invalid and not available (SFINAE). 00047 template<typename ExprScalar,typename T, bool IsSupported> 00048 struct promote_scalar_arg; 00049 00050 template<typename S,typename T> 00051 struct promote_scalar_arg<S,T,true> 00052 { 00053 typedef T type; 00054 }; 00055 00056 // Recursively check safe conversion to PromotedType, and then ExprScalar if they are different. 00057 template<typename ExprScalar,typename T,typename PromotedType, 00058 bool ConvertibleToLiteral = internal::is_convertible<T,PromotedType>::value, 00059 bool IsSafe = NumTraits<T>::IsInteger || !NumTraits<PromotedType>::IsInteger> 00060 struct promote_scalar_arg_unsupported; 00061 00062 // Start recursion with NumTraits<ExprScalar>::Literal 00063 template<typename S,typename T> 00064 struct promote_scalar_arg<S,T,false> : promote_scalar_arg_unsupported<S,T,typename NumTraits<S>::Literal> {}; 00065 00066 // We found a match! 00067 template<typename S,typename T, typename PromotedType> 00068 struct promote_scalar_arg_unsupported<S,T,PromotedType,true,true> 00069 { 00070 typedef PromotedType type; 00071 }; 00072 00073 // No match, but no real-to-integer issues, and ExprScalar and current PromotedType are different, 00074 // so let's try to promote to ExprScalar 00075 template<typename ExprScalar,typename T, typename PromotedType> 00076 struct promote_scalar_arg_unsupported<ExprScalar,T,PromotedType,false,true> 00077 : promote_scalar_arg_unsupported<ExprScalar,T,ExprScalar> 00078 {}; 00079 00080 // Unsafe real-to-integer, let's stop. 00081 template<typename S,typename T, typename PromotedType, bool ConvertibleToLiteral> 00082 struct promote_scalar_arg_unsupported<S,T,PromotedType,ConvertibleToLiteral,false> {}; 00083 00084 // T is not even convertible to ExprScalar, let's stop. 00085 template<typename S,typename T> 00086 struct promote_scalar_arg_unsupported<S,T,S,false,true> {}; 00087 00088 //classes inheriting no_assignment_operator don't generate a default operator=. 00089 class no_assignment_operator 00090 { 00091 private: 00092 no_assignment_operator& operator=(const no_assignment_operator&); 00093 }; 00094 00096 template<typename I1, typename I2> 00097 struct promote_index_type 00098 { 00099 typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type; 00100 }; 00101 00106 template<typename T, int Value> class variable_if_dynamic 00107 { 00108 public: 00109 EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic) 00110 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); } 00111 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T value() { return T(Value); } 00112 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T) {} 00113 }; 00114 00115 template<typename T> class variable_if_dynamic<T, Dynamic> 00116 { 00117 T m_value; 00118 EIGEN_DEVICE_FUNC variable_if_dynamic() { eigen_assert(false); } 00119 public: 00120 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value) : m_value(value) {} 00121 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; } 00122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; } 00123 }; 00124 00127 template<typename T, int Value> class variable_if_dynamicindex 00128 { 00129 public: 00130 EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex) 00131 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); } 00132 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T value() { return T(Value); } 00133 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T) {} 00134 }; 00135 00136 template<typename T> class variable_if_dynamicindex<T, DynamicIndex> 00137 { 00138 T m_value; 00139 EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); } 00140 public: 00141 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T value) : m_value(value) {} 00142 EIGEN_DEVICE_FUNC T EIGEN_STRONG_INLINE value() const { return m_value; } 00143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; } 00144 }; 00145 00146 template<typename T> struct functor_traits 00147 { 00148 enum 00149 { 00150 Cost = 10, 00151 PacketAccess = false, 00152 IsRepeatable = false 00153 }; 00154 }; 00155 00156 template<typename T> struct packet_traits; 00157 00158 template<typename T> struct unpacket_traits 00159 { 00160 typedef T type; 00161 typedef T half; 00162 enum 00163 { 00164 size = 1, 00165 alignment = 1 00166 }; 00167 }; 00168 00169 template<int Size, typename PacketType, 00170 bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value> 00171 struct find_best_packet_helper; 00172 00173 template< int Size, typename PacketType> 00174 struct find_best_packet_helper<Size,PacketType,true> 00175 { 00176 typedef PacketType type; 00177 }; 00178 00179 template<int Size, typename PacketType> 00180 struct find_best_packet_helper<Size,PacketType,false> 00181 { 00182 typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type; 00183 }; 00184 00185 template<typename T, int Size> 00186 struct find_best_packet 00187 { 00188 typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type; 00189 }; 00190 00191 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 00192 template<int ArrayBytes, int AlignmentBytes, 00193 bool Match = bool((ArrayBytes%AlignmentBytes)==0), 00194 bool TryHalf = bool(EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) > 00195 struct compute_default_alignment_helper 00196 { 00197 enum { value = 0 }; 00198 }; 00199 00200 template<int ArrayBytes, int AlignmentBytes, bool TryHalf> 00201 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, true, TryHalf> // Match 00202 { 00203 enum { value = AlignmentBytes }; 00204 }; 00205 00206 template<int ArrayBytes, int AlignmentBytes> 00207 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, false, true> // Try-half 00208 { 00209 // current packet too large, try with an half-packet 00210 enum { value = compute_default_alignment_helper<ArrayBytes, AlignmentBytes/2>::value }; 00211 }; 00212 #else 00213 // If static alignment is disabled, no need to bother. 00214 // This also avoids a division by zero in "bool Match = bool((ArrayBytes%AlignmentBytes)==0)" 00215 template<int ArrayBytes, int AlignmentBytes> 00216 struct compute_default_alignment_helper 00217 { 00218 enum { value = 0 }; 00219 }; 00220 #endif 00221 00222 template<typename T, int Size> struct compute_default_alignment { 00223 enum { value = compute_default_alignment_helper<Size*sizeof(T),EIGEN_MAX_STATIC_ALIGN_BYTES>::value }; 00224 }; 00225 00226 template<typename T> struct compute_default_alignment<T,Dynamic> { 00227 enum { value = EIGEN_MAX_ALIGN_BYTES }; 00228 }; 00229 00230 template<typename _Scalar, int _Rows, int _Cols, 00231 int _Options = AutoAlign | 00232 ( (_Rows==1 && _Cols!=1) ? RowMajor 00233 : (_Cols==1 && _Rows!=1) ? ColMajor 00234 : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ), 00235 int _MaxRows = _Rows, 00236 int _MaxCols = _Cols 00237 > class make_proper_matrix_type 00238 { 00239 enum { 00240 IsColVector = _Cols==1 && _Rows!=1, 00241 IsRowVector = _Rows==1 && _Cols!=1, 00242 Options = IsColVector ? (_Options | ColMajor) & ~RowMajor 00243 : IsRowVector ? (_Options | RowMajor) & ~ColMajor 00244 : _Options 00245 }; 00246 public: 00247 typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type; 00248 }; 00249 00250 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> 00251 class compute_matrix_flags 00252 { 00253 enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 }; 00254 public: 00255 // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<> 00256 // and then propagate this information to the evaluator's flags. 00257 // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage. 00258 enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit }; 00259 }; 00260 00261 template<int _Rows, int _Cols> struct size_at_compile_time 00262 { 00263 enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols }; 00264 }; 00265 00266 template<typename XprType> struct size_of_xpr_at_compile_time 00267 { 00268 enum { ret = size_at_compile_time<traits<XprType>::RowsAtCompileTime,traits<XprType>::ColsAtCompileTime>::ret }; 00269 }; 00270 00271 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type, 00272 * whereas eval is a const reference in the case of a matrix 00273 */ 00274 00275 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type; 00276 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense; 00277 template<typename T> struct plain_matrix_type<T,Dense> 00278 { 00279 typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type; 00280 }; 00281 template<typename T> struct plain_matrix_type<T,DiagonalShape> 00282 { 00283 typedef typename T::PlainObject type; 00284 }; 00285 00286 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags> 00287 { 00288 typedef Matrix<typename traits<T>::Scalar, 00289 traits<T>::RowsAtCompileTime, 00290 traits<T>::ColsAtCompileTime, 00291 AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor), 00292 traits<T>::MaxRowsAtCompileTime, 00293 traits<T>::MaxColsAtCompileTime 00294 > type; 00295 }; 00296 00297 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags> 00298 { 00299 typedef Array<typename traits<T>::Scalar, 00300 traits<T>::RowsAtCompileTime, 00301 traits<T>::ColsAtCompileTime, 00302 AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor), 00303 traits<T>::MaxRowsAtCompileTime, 00304 traits<T>::MaxColsAtCompileTime 00305 > type; 00306 }; 00307 00308 /* eval : the return type of eval(). For matrices, this is just a const reference 00309 * in order to avoid a useless copy 00310 */ 00311 00312 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval; 00313 00314 template<typename T> struct eval<T,Dense> 00315 { 00316 typedef typename plain_matrix_type<T>::type type; 00317 // typedef typename T::PlainObject type; 00318 // typedef T::Matrix<typename traits<T>::Scalar, 00319 // traits<T>::RowsAtCompileTime, 00320 // traits<T>::ColsAtCompileTime, 00321 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor), 00322 // traits<T>::MaxRowsAtCompileTime, 00323 // traits<T>::MaxColsAtCompileTime 00324 // > type; 00325 }; 00326 00327 template<typename T> struct eval<T,DiagonalShape> 00328 { 00329 typedef typename plain_matrix_type<T>::type type; 00330 }; 00331 00332 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy 00333 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 00334 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense> 00335 { 00336 typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; 00337 }; 00338 00339 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 00340 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense> 00341 { 00342 typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; 00343 }; 00344 00345 00346 /* similar to plain_matrix_type, but using the evaluator's Flags */ 00347 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval; 00348 00349 template<typename T> 00350 struct plain_object_eval<T,Dense> 00351 { 00352 typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type; 00353 }; 00354 00355 00356 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major 00357 */ 00358 template<typename T> struct plain_matrix_type_column_major 00359 { 00360 enum { Rows = traits<T>::RowsAtCompileTime, 00361 Cols = traits<T>::ColsAtCompileTime, 00362 MaxRows = traits<T>::MaxRowsAtCompileTime, 00363 MaxCols = traits<T>::MaxColsAtCompileTime 00364 }; 00365 typedef Matrix<typename traits<T>::Scalar, 00366 Rows, 00367 Cols, 00368 (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor, 00369 MaxRows, 00370 MaxCols 00371 > type; 00372 }; 00373 00374 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major 00375 */ 00376 template<typename T> struct plain_matrix_type_row_major 00377 { 00378 enum { Rows = traits<T>::RowsAtCompileTime, 00379 Cols = traits<T>::ColsAtCompileTime, 00380 MaxRows = traits<T>::MaxRowsAtCompileTime, 00381 MaxCols = traits<T>::MaxColsAtCompileTime 00382 }; 00383 typedef Matrix<typename traits<T>::Scalar, 00384 Rows, 00385 Cols, 00386 (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor, 00387 MaxRows, 00388 MaxCols 00389 > type; 00390 }; 00391 00395 template <typename T> 00396 struct ref_selector 00397 { 00398 typedef typename conditional< 00399 bool(traits<T>::Flags & NestByRefBit), 00400 T const&, 00401 const T 00402 >::type type; 00403 00404 typedef typename conditional< 00405 bool(traits<T>::Flags & NestByRefBit), 00406 T &, 00407 T 00408 >::type non_const_type; 00409 }; 00410 00412 template<typename T1, typename T2> 00413 struct transfer_constness 00414 { 00415 typedef typename conditional< 00416 bool(internal::is_const<T1>::value), 00417 typename internal::add_const_on_value_type<T2>::type, 00418 T2 00419 >::type type; 00420 }; 00421 00422 00423 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time 00424 // has to be evaluated into a temporary. 00425 // That's the purpose of this new nested_eval helper: 00437 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval 00438 { 00439 enum { 00440 ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost, 00441 CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory? 00442 // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1. 00443 // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON 00444 // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators. 00445 // Another solution could be to count the number of temps? 00446 NAsInteger = n == Dynamic ? HugeCost : n, 00447 CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost, 00448 CostNoEval = NAsInteger * CoeffReadCost, 00449 Evaluate = (int(evaluator<T>::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval)) 00450 }; 00451 00452 typedef typename conditional<Evaluate, PlainObject, typename ref_selector<T>::type>::type type; 00453 }; 00454 00455 template<typename T> 00456 EIGEN_DEVICE_FUNC 00457 inline T* const_cast_ptr(const T* ptr) 00458 { 00459 return const_cast<T*>(ptr); 00460 } 00461 00462 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind> 00463 struct dense_xpr_base 00464 { 00465 /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */ 00466 }; 00467 00468 template<typename Derived> 00469 struct dense_xpr_base<Derived, MatrixXpr> 00470 { 00471 typedef MatrixBase<Derived> type; 00472 }; 00473 00474 template<typename Derived> 00475 struct dense_xpr_base<Derived, ArrayXpr> 00476 { 00477 typedef ArrayBase<Derived> type; 00478 }; 00479 00480 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind> 00481 struct generic_xpr_base; 00482 00483 template<typename Derived, typename XprKind> 00484 struct generic_xpr_base<Derived, XprKind, Dense> 00485 { 00486 typedef typename dense_xpr_base<Derived,XprKind>::type type; 00487 }; 00488 00489 template<typename XprType, typename CastType> struct cast_return_type 00490 { 00491 typedef typename XprType::Scalar CurrentScalarType; 00492 typedef typename remove_all<CastType>::type _CastType; 00493 typedef typename _CastType::Scalar NewScalarType; 00494 typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value, 00495 const XprType&,CastType>::type type; 00496 }; 00497 00498 template <typename A, typename B> struct promote_storage_type; 00499 00500 template <typename A> struct promote_storage_type<A,A> 00501 { 00502 typedef A ret; 00503 }; 00504 template <typename A> struct promote_storage_type<A, const A> 00505 { 00506 typedef A ret; 00507 }; 00508 template <typename A> struct promote_storage_type<const A, A> 00509 { 00510 typedef A ret; 00511 }; 00512 00526 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type; 00527 00528 template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; }; 00529 template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; }; 00530 template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; }; 00531 template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; }; 00532 template <typename Functor> struct cwise_promote_storage_type<Sparse,Dense,Functor> { typedef Sparse ret; }; 00533 template <typename Functor> struct cwise_promote_storage_type<Dense,Sparse,Functor> { typedef Sparse ret; }; 00534 00535 template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order { 00536 enum { value = LhsOrder }; 00537 }; 00538 00539 template <typename LhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder> { enum { value = RhsOrder }; }; 00540 template <typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder> { enum { value = LhsOrder }; }; 00541 template <int Order> struct cwise_promote_storage_order<Sparse,Sparse,Order,Order> { enum { value = Order }; }; 00542 00543 00558 template <typename A, typename B, int ProductTag> struct product_promote_storage_type; 00559 00560 template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;}; 00561 template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;}; 00562 template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; }; 00563 template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; }; 00564 00565 template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; }; 00566 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; }; 00567 template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; }; 00568 template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; }; 00569 00570 template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; }; 00571 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; }; 00572 template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; }; 00573 template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; }; 00574 00578 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00579 struct plain_row_type 00580 { 00581 typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime, 00582 ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType; 00583 typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime, 00584 ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType; 00585 00586 typedef typename conditional< 00587 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00588 MatrixRowType, 00589 ArrayRowType 00590 >::type type; 00591 }; 00592 00593 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00594 struct plain_col_type 00595 { 00596 typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1, 00597 ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType; 00598 typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1, 00599 ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType; 00600 00601 typedef typename conditional< 00602 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00603 MatrixColType, 00604 ArrayColType 00605 >::type type; 00606 }; 00607 00608 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar> 00609 struct plain_diag_type 00610 { 00611 enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime), 00612 max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime) 00613 }; 00614 typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType; 00615 typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType; 00616 00617 typedef typename conditional< 00618 is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value, 00619 MatrixDiagType, 00620 ArrayDiagType 00621 >::type type; 00622 }; 00623 00624 template<typename Expr,typename Scalar = typename Expr::Scalar> 00625 struct plain_constant_type 00626 { 00627 enum { Options = (traits<Expr>::Flags&RowMajorBit)?RowMajor:0 }; 00628 00629 typedef Array<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime, 00630 Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> array_type; 00631 00632 typedef Matrix<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime, 00633 Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> matrix_type; 00634 00635 typedef CwiseNullaryOp<scalar_constant_op<Scalar>, const typename conditional<is_same< typename traits<Expr>::XprKind, MatrixXpr >::value, matrix_type, array_type>::type > type; 00636 }; 00637 00638 template<typename ExpressionType> 00639 struct is_lvalue 00640 { 00641 enum { value = (!bool(is_const<ExpressionType>::value)) && 00642 bool(traits<ExpressionType>::Flags & LvalueBit) }; 00643 }; 00644 00645 template<typename T> struct is_diagonal 00646 { enum { ret = false }; }; 00647 00648 template<typename T> struct is_diagonal<DiagonalBase<T> > 00649 { enum { ret = true }; }; 00650 00651 template<typename T> struct is_diagonal<DiagonalWrapper<T> > 00652 { enum { ret = true }; }; 00653 00654 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> > 00655 { enum { ret = true }; }; 00656 00657 template<typename S1, typename S2> struct glue_shapes; 00658 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; }; 00659 00660 template<typename T1, typename T2> 00661 bool is_same_dense(const T1 &mat1, const T2 &mat2, typename enable_if<has_direct_access<T1>::ret&&has_direct_access<T2>::ret, T1>::type * = 0) 00662 { 00663 return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride()); 00664 } 00665 00666 template<typename T1, typename T2> 00667 bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_access<T1>::ret&&has_direct_access<T2>::ret), T1>::type * = 0) 00668 { 00669 return false; 00670 } 00671 00672 // Internal helper defining the cost of a scalar division for the type T. 00673 // The default heuristic can be specialized for each scalar type and architecture. 00674 template<typename T,bool Vectorized=false,typename EnaleIf = void> 00675 struct scalar_div_cost { 00676 enum { value = 8*NumTraits<T>::MulCost }; 00677 }; 00678 00679 template<typename T,bool Vectorized> 00680 struct scalar_div_cost<std::complex<T>, Vectorized> { 00681 enum { value = 2*scalar_div_cost<T>::value 00682 + 6*NumTraits<T>::MulCost 00683 + 3*NumTraits<T>::AddCost 00684 }; 00685 }; 00686 00687 00688 template<bool Vectorized> 00689 struct scalar_div_cost<signed long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 24 }; }; 00690 template<bool Vectorized> 00691 struct scalar_div_cost<unsigned long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 21 }; }; 00692 00693 00694 #ifdef EIGEN_DEBUG_ASSIGN 00695 std::string demangle_traversal(int t) 00696 { 00697 if(t==DefaultTraversal) return "DefaultTraversal"; 00698 if(t==LinearTraversal) return "LinearTraversal"; 00699 if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal"; 00700 if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal"; 00701 if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal"; 00702 return "?"; 00703 } 00704 std::string demangle_unrolling(int t) 00705 { 00706 if(t==NoUnrolling) return "NoUnrolling"; 00707 if(t==InnerUnrolling) return "InnerUnrolling"; 00708 if(t==CompleteUnrolling) return "CompleteUnrolling"; 00709 return "?"; 00710 } 00711 std::string demangle_flags(int f) 00712 { 00713 std::string res; 00714 if(f&RowMajorBit) res += " | RowMajor"; 00715 if(f&PacketAccessBit) res += " | Packet"; 00716 if(f&LinearAccessBit) res += " | Linear"; 00717 if(f&LvalueBit) res += " | Lvalue"; 00718 if(f&DirectAccessBit) res += " | Direct"; 00719 if(f&NestByRefBit) res += " | NestByRef"; 00720 if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit"; 00721 00722 return res; 00723 } 00724 #endif 00725 00726 } // end namespace internal 00727 00728 00765 template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> > 00766 struct ScalarBinaryOpTraits 00767 #ifndef EIGEN_PARSED_BY_DOXYGEN 00768 // for backward compatibility, use the hints given by the (deprecated) internal::scalar_product_traits class. 00769 : internal::scalar_product_traits<ScalarA,ScalarB> 00770 #endif // EIGEN_PARSED_BY_DOXYGEN 00771 {}; 00772 00773 template<typename T, typename BinaryOp> 00774 struct ScalarBinaryOpTraits<T,T,BinaryOp> 00775 { 00776 typedef T ReturnType; 00777 }; 00778 00779 template <typename T, typename BinaryOp> 00780 struct ScalarBinaryOpTraits<T, typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, BinaryOp> 00781 { 00782 typedef T ReturnType; 00783 }; 00784 template <typename T, typename BinaryOp> 00785 struct ScalarBinaryOpTraits<typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, T, BinaryOp> 00786 { 00787 typedef T ReturnType; 00788 }; 00789 00790 // For Matrix * Permutation 00791 template<typename T, typename BinaryOp> 00792 struct ScalarBinaryOpTraits<T,void,BinaryOp> 00793 { 00794 typedef T ReturnType; 00795 }; 00796 00797 // For Permutation * Matrix 00798 template<typename T, typename BinaryOp> 00799 struct ScalarBinaryOpTraits<void,T,BinaryOp> 00800 { 00801 typedef T ReturnType; 00802 }; 00803 00804 // for Permutation*Permutation 00805 template<typename BinaryOp> 00806 struct ScalarBinaryOpTraits<void,void,BinaryOp> 00807 { 00808 typedef void ReturnType; 00809 }; 00810 00811 // We require Lhs and Rhs to have "compatible" scalar types. 00812 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. 00813 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to 00814 // add together a float matrix and a double matrix. 00815 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ 00816 EIGEN_STATIC_ASSERT((Eigen::internal::has_ReturnType<ScalarBinaryOpTraits<LHS, RHS,BINOP> >::value), \ 00817 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 00818 00819 } // end namespace Eigen 00820 00821 #endif // EIGEN_XPRHELPER_H