Eigen  3.3.3
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 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
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends