cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

XprHelper.h (35762B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
      5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_XPRHELPER_H
     12 #define EIGEN_XPRHELPER_H
     13 
     14 // just a workaround because GCC seems to not really like empty structs
     15 // FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled
     16 // so currently we simply disable this optimization for gcc 4.3
     17 #if EIGEN_COMP_GNUC && !EIGEN_GNUC_AT(4,3)
     18   #define EIGEN_EMPTY_STRUCT_CTOR(X) \
     19     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X() {} \
     20     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X(const X& ) {}
     21 #else
     22   #define EIGEN_EMPTY_STRUCT_CTOR(X)
     23 #endif
     24 
     25 namespace Eigen {
     26 
     27 namespace internal {
     28 
     29 template<typename IndexDest, typename IndexSrc>
     30 EIGEN_DEVICE_FUNC
     31 inline IndexDest convert_index(const IndexSrc& idx) {
     32   // for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away:
     33   eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value to big for target type");
     34   return IndexDest(idx);
     35 }
     36 
     37 // true if T can be considered as an integral index (i.e., and integral type or enum)
     38 template<typename T> struct is_valid_index_type
     39 {
     40   enum { value =
     41 #if EIGEN_HAS_TYPE_TRAITS
     42     internal::is_integral<T>::value || std::is_enum<T>::value
     43 #elif EIGEN_COMP_MSVC
     44     internal::is_integral<T>::value || __is_enum(T)
     45 #else
     46     // without C++11, we use is_convertible to Index instead of is_integral in order to treat enums as Index.
     47     internal::is_convertible<T,Index>::value && !internal::is_same<T,float>::value && !is_same<T,double>::value
     48 #endif
     49   };
     50 };
     51 
     52 // true if both types are not valid index types
     53 template<typename RowIndices, typename ColIndices>
     54 struct valid_indexed_view_overload {
     55   enum { value = !(internal::is_valid_index_type<RowIndices>::value && internal::is_valid_index_type<ColIndices>::value) };
     56 };
     57 
     58 // promote_scalar_arg is an helper used in operation between an expression and a scalar, like:
     59 //    expression * scalar
     60 // 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.
     61 // 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.
     62 // Then the logic is as follows:
     63 //  - if the operation is natively supported as defined by IsSupported, then the scalar type is not promoted, and T is returned.
     64 //  - 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.
     65 //  - otherwise, ExprScalar is returned if T is implicitly convertible to ExprScalar AND that this does not imply a float to integer conversion.
     66 //  - In all other cases, the promoted type is not defined, and the respective operation is thus invalid and not available (SFINAE).
     67 template<typename ExprScalar,typename T, bool IsSupported>
     68 struct promote_scalar_arg;
     69 
     70 template<typename S,typename T>
     71 struct promote_scalar_arg<S,T,true>
     72 {
     73   typedef T type;
     74 };
     75 
     76 // Recursively check safe conversion to PromotedType, and then ExprScalar if they are different.
     77 template<typename ExprScalar,typename T,typename PromotedType,
     78   bool ConvertibleToLiteral = internal::is_convertible<T,PromotedType>::value,
     79   bool IsSafe = NumTraits<T>::IsInteger || !NumTraits<PromotedType>::IsInteger>
     80 struct promote_scalar_arg_unsupported;
     81 
     82 // Start recursion with NumTraits<ExprScalar>::Literal
     83 template<typename S,typename T>
     84 struct promote_scalar_arg<S,T,false> : promote_scalar_arg_unsupported<S,T,typename NumTraits<S>::Literal> {};
     85 
     86 // We found a match!
     87 template<typename S,typename T, typename PromotedType>
     88 struct promote_scalar_arg_unsupported<S,T,PromotedType,true,true>
     89 {
     90   typedef PromotedType type;
     91 };
     92 
     93 // No match, but no real-to-integer issues, and ExprScalar and current PromotedType are different,
     94 // so let's try to promote to ExprScalar
     95 template<typename ExprScalar,typename T, typename PromotedType>
     96 struct promote_scalar_arg_unsupported<ExprScalar,T,PromotedType,false,true>
     97    : promote_scalar_arg_unsupported<ExprScalar,T,ExprScalar>
     98 {};
     99 
    100 // Unsafe real-to-integer, let's stop.
    101 template<typename S,typename T, typename PromotedType, bool ConvertibleToLiteral>
    102 struct promote_scalar_arg_unsupported<S,T,PromotedType,ConvertibleToLiteral,false> {};
    103 
    104 // T is not even convertible to ExprScalar, let's stop.
    105 template<typename S,typename T>
    106 struct promote_scalar_arg_unsupported<S,T,S,false,true> {};
    107 
    108 //classes inheriting no_assignment_operator don't generate a default operator=.
    109 class no_assignment_operator
    110 {
    111   private:
    112     no_assignment_operator& operator=(const no_assignment_operator&);
    113   protected:
    114     EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator)
    115     EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator)
    116 };
    117 
    118 /** \internal return the index type with the largest number of bits */
    119 template<typename I1, typename I2>
    120 struct promote_index_type
    121 {
    122   typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
    123 };
    124 
    125 /** \internal If the template parameter Value is Dynamic, this class is just a wrapper around a T variable that
    126   * can be accessed using value() and setValue().
    127   * Otherwise, this class is an empty structure and value() just returns the template parameter Value.
    128   */
    129 template<typename T, int Value> class variable_if_dynamic
    130 {
    131   public:
    132     EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(variable_if_dynamic)
    133     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
    134     EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
    135     T value() { return T(Value); }
    136     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
    137     operator T() const { return T(Value); }
    138     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
    139     void setValue(T v) const { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
    140 };
    141 
    142 template<typename T> class variable_if_dynamic<T, Dynamic>
    143 {
    144     T m_value;
    145   public:
    146     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value = 0) EIGEN_NO_THROW : m_value(value) {}
    147     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; }
    148     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator T() const { return m_value; }
    149     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
    150 };
    151 
    152 /** \internal like variable_if_dynamic but for DynamicIndex
    153   */
    154 template<typename T, int Value> class variable_if_dynamicindex
    155 {
    156   public:
    157     EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex)
    158     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
    159     EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
    160     T value() { return T(Value); }
    161     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
    162     void setValue(T) {}
    163 };
    164 
    165 template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
    166 {
    167     T m_value;
    168     EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
    169   public:
    170     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T value) : m_value(value) {}
    171     EIGEN_DEVICE_FUNC T EIGEN_STRONG_INLINE value() const { return m_value; }
    172     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
    173 };
    174 
    175 template<typename T> struct functor_traits
    176 {
    177   enum
    178   {
    179     Cost = 10,
    180     PacketAccess = false,
    181     IsRepeatable = false
    182   };
    183 };
    184 
    185 template<typename T> struct packet_traits;
    186 
    187 template<typename T> struct unpacket_traits;
    188 
    189 template<int Size, typename PacketType,
    190          bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
    191 struct find_best_packet_helper;
    192 
    193 template< int Size, typename PacketType>
    194 struct find_best_packet_helper<Size,PacketType,true>
    195 {
    196   typedef PacketType type;
    197 };
    198 
    199 template<int Size, typename PacketType>
    200 struct find_best_packet_helper<Size,PacketType,false>
    201 {
    202   typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
    203 };
    204 
    205 template<typename T, int Size>
    206 struct find_best_packet
    207 {
    208   typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
    209 };
    210 
    211 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
    212 template<int ArrayBytes, int AlignmentBytes,
    213          bool Match     =  bool((ArrayBytes%AlignmentBytes)==0),
    214          bool TryHalf   =  bool(EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) >
    215 struct compute_default_alignment_helper
    216 {
    217   enum { value = 0 };
    218 };
    219 
    220 template<int ArrayBytes, int AlignmentBytes, bool TryHalf>
    221 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, true, TryHalf> // Match
    222 {
    223   enum { value = AlignmentBytes };
    224 };
    225 
    226 template<int ArrayBytes, int AlignmentBytes>
    227 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, false, true> // Try-half
    228 {
    229   // current packet too large, try with an half-packet
    230   enum { value = compute_default_alignment_helper<ArrayBytes, AlignmentBytes/2>::value };
    231 };
    232 #else
    233 // If static alignment is disabled, no need to bother.
    234 // This also avoids a division by zero in "bool Match =  bool((ArrayBytes%AlignmentBytes)==0)"
    235 template<int ArrayBytes, int AlignmentBytes>
    236 struct compute_default_alignment_helper
    237 {
    238   enum { value = 0 };
    239 };
    240 #endif
    241 
    242 template<typename T, int Size> struct compute_default_alignment {
    243   enum { value = compute_default_alignment_helper<Size*sizeof(T),EIGEN_MAX_STATIC_ALIGN_BYTES>::value };
    244 };
    245 
    246 template<typename T> struct compute_default_alignment<T,Dynamic> {
    247   enum { value = EIGEN_MAX_ALIGN_BYTES };
    248 };
    249 
    250 template<typename _Scalar, int _Rows, int _Cols,
    251          int _Options = AutoAlign |
    252                           ( (_Rows==1 && _Cols!=1) ? RowMajor
    253                           : (_Cols==1 && _Rows!=1) ? ColMajor
    254                           : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
    255          int _MaxRows = _Rows,
    256          int _MaxCols = _Cols
    257 > class make_proper_matrix_type
    258 {
    259     enum {
    260       IsColVector = _Cols==1 && _Rows!=1,
    261       IsRowVector = _Rows==1 && _Cols!=1,
    262       Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
    263               : IsRowVector ? (_Options | RowMajor) & ~ColMajor
    264               : _Options
    265     };
    266   public:
    267     typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
    268 };
    269 
    270 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    271 class compute_matrix_flags
    272 {
    273     enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 };
    274   public:
    275     // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
    276     // and then propagate this information to the evaluator's flags.
    277     // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
    278     enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit };
    279 };
    280 
    281 template<int _Rows, int _Cols> struct size_at_compile_time
    282 {
    283   enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
    284 };
    285 
    286 template<typename XprType> struct size_of_xpr_at_compile_time
    287 {
    288   enum { ret = size_at_compile_time<traits<XprType>::RowsAtCompileTime,traits<XprType>::ColsAtCompileTime>::ret };
    289 };
    290 
    291 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
    292  * whereas eval is a const reference in the case of a matrix
    293  */
    294 
    295 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
    296 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
    297 template<typename T> struct plain_matrix_type<T,Dense>
    298 {
    299   typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
    300 };
    301 template<typename T> struct plain_matrix_type<T,DiagonalShape>
    302 {
    303   typedef typename T::PlainObject type;
    304 };
    305 
    306 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
    307 {
    308   typedef Matrix<typename traits<T>::Scalar,
    309                 traits<T>::RowsAtCompileTime,
    310                 traits<T>::ColsAtCompileTime,
    311                 AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
    312                 traits<T>::MaxRowsAtCompileTime,
    313                 traits<T>::MaxColsAtCompileTime
    314           > type;
    315 };
    316 
    317 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
    318 {
    319   typedef Array<typename traits<T>::Scalar,
    320                 traits<T>::RowsAtCompileTime,
    321                 traits<T>::ColsAtCompileTime,
    322                 AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
    323                 traits<T>::MaxRowsAtCompileTime,
    324                 traits<T>::MaxColsAtCompileTime
    325           > type;
    326 };
    327 
    328 /* eval : the return type of eval(). For matrices, this is just a const reference
    329  * in order to avoid a useless copy
    330  */
    331 
    332 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
    333 
    334 template<typename T> struct eval<T,Dense>
    335 {
    336   typedef typename plain_matrix_type<T>::type type;
    337 //   typedef typename T::PlainObject type;
    338 //   typedef T::Matrix<typename traits<T>::Scalar,
    339 //                 traits<T>::RowsAtCompileTime,
    340 //                 traits<T>::ColsAtCompileTime,
    341 //                 AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
    342 //                 traits<T>::MaxRowsAtCompileTime,
    343 //                 traits<T>::MaxColsAtCompileTime
    344 //           > type;
    345 };
    346 
    347 template<typename T> struct eval<T,DiagonalShape>
    348 {
    349   typedef typename plain_matrix_type<T>::type type;
    350 };
    351 
    352 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
    353 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
    354 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
    355 {
    356   typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
    357 };
    358 
    359 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
    360 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
    361 {
    362   typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
    363 };
    364 
    365 
    366 /* similar to plain_matrix_type, but using the evaluator's Flags */
    367 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
    368 
    369 template<typename T>
    370 struct plain_object_eval<T,Dense>
    371 {
    372   typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
    373 };
    374 
    375 
    376 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
    377  */
    378 template<typename T> struct plain_matrix_type_column_major
    379 {
    380   enum { Rows = traits<T>::RowsAtCompileTime,
    381          Cols = traits<T>::ColsAtCompileTime,
    382          MaxRows = traits<T>::MaxRowsAtCompileTime,
    383          MaxCols = traits<T>::MaxColsAtCompileTime
    384   };
    385   typedef Matrix<typename traits<T>::Scalar,
    386                 Rows,
    387                 Cols,
    388                 (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
    389                 MaxRows,
    390                 MaxCols
    391           > type;
    392 };
    393 
    394 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
    395  */
    396 template<typename T> struct plain_matrix_type_row_major
    397 {
    398   enum { Rows = traits<T>::RowsAtCompileTime,
    399          Cols = traits<T>::ColsAtCompileTime,
    400          MaxRows = traits<T>::MaxRowsAtCompileTime,
    401          MaxCols = traits<T>::MaxColsAtCompileTime
    402   };
    403   typedef Matrix<typename traits<T>::Scalar,
    404                 Rows,
    405                 Cols,
    406                 (MaxCols==1&&MaxRows!=1) ? ColMajor : RowMajor,
    407                 MaxRows,
    408                 MaxCols
    409           > type;
    410 };
    411 
    412 /** \internal The reference selector for template expressions. The idea is that we don't
    413   * need to use references for expressions since they are light weight proxy
    414   * objects which should generate no copying overhead. */
    415 template <typename T>
    416 struct ref_selector
    417 {
    418   typedef typename conditional<
    419     bool(traits<T>::Flags & NestByRefBit),
    420     T const&,
    421     const T
    422   >::type type;
    423 
    424   typedef typename conditional<
    425     bool(traits<T>::Flags & NestByRefBit),
    426     T &,
    427     T
    428   >::type non_const_type;
    429 };
    430 
    431 /** \internal Adds the const qualifier on the value-type of T2 if and only if T1 is a const type */
    432 template<typename T1, typename T2>
    433 struct transfer_constness
    434 {
    435   typedef typename conditional<
    436     bool(internal::is_const<T1>::value),
    437     typename internal::add_const_on_value_type<T2>::type,
    438     T2
    439   >::type type;
    440 };
    441 
    442 
    443 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time
    444 // has to be evaluated into a temporary.
    445 // That's the purpose of this new nested_eval helper:
    446 /** \internal Determines how a given expression should be nested when evaluated multiple times.
    447   * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
    448   * evaluated into the bigger product expression. The choice is between nesting the expression b+c as-is, or
    449   * evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is
    450   * a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes
    451   * many coefficient accesses in the nested expressions -- as is the case with matrix product for example.
    452   *
    453   * \tparam T the type of the expression being nested.
    454   * \tparam n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression.
    455   * \tparam PlainObject the type of the temporary if needed.
    456   */
    457 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
    458 {
    459   enum {
    460     ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
    461     CoeffReadCost = evaluator<T>::CoeffReadCost,  // NOTE What if an evaluator evaluate itself into a temporary?
    462                                                   //      Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
    463                                                   //      This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
    464                                                   //      for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
    465                                                   //      Another solution could be to count the number of temps?
    466     NAsInteger = n == Dynamic ? HugeCost : n,
    467     CostEval   = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
    468     CostNoEval = NAsInteger * CoeffReadCost,
    469     Evaluate = (int(evaluator<T>::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval))
    470   };
    471 
    472   typedef typename conditional<Evaluate, PlainObject, typename ref_selector<T>::type>::type type;
    473 };
    474 
    475 template<typename T>
    476 EIGEN_DEVICE_FUNC
    477 inline T* const_cast_ptr(const T* ptr)
    478 {
    479   return const_cast<T*>(ptr);
    480 }
    481 
    482 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
    483 struct dense_xpr_base
    484 {
    485   /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
    486 };
    487 
    488 template<typename Derived>
    489 struct dense_xpr_base<Derived, MatrixXpr>
    490 {
    491   typedef MatrixBase<Derived> type;
    492 };
    493 
    494 template<typename Derived>
    495 struct dense_xpr_base<Derived, ArrayXpr>
    496 {
    497   typedef ArrayBase<Derived> type;
    498 };
    499 
    500 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
    501 struct generic_xpr_base;
    502 
    503 template<typename Derived, typename XprKind>
    504 struct generic_xpr_base<Derived, XprKind, Dense>
    505 {
    506   typedef typename dense_xpr_base<Derived,XprKind>::type type;
    507 };
    508 
    509 template<typename XprType, typename CastType> struct cast_return_type
    510 {
    511   typedef typename XprType::Scalar CurrentScalarType;
    512   typedef typename remove_all<CastType>::type _CastType;
    513   typedef typename _CastType::Scalar NewScalarType;
    514   typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
    515                               const XprType&,CastType>::type type;
    516 };
    517 
    518 template <typename A, typename B> struct promote_storage_type;
    519 
    520 template <typename A> struct promote_storage_type<A,A>
    521 {
    522   typedef A ret;
    523 };
    524 template <typename A> struct promote_storage_type<A, const A>
    525 {
    526   typedef A ret;
    527 };
    528 template <typename A> struct promote_storage_type<const A, A>
    529 {
    530   typedef A ret;
    531 };
    532 
    533 /** \internal Specify the "storage kind" of applying a coefficient-wise
    534   * binary operations between two expressions of kinds A and B respectively.
    535   * The template parameter Functor permits to specialize the resulting storage kind wrt to
    536   * the functor.
    537   * The default rules are as follows:
    538   * \code
    539   * A      op A      -> A
    540   * A      op dense  -> dense
    541   * dense  op B      -> dense
    542   * sparse op dense  -> sparse
    543   * dense  op sparse -> sparse
    544   * \endcode
    545   */
    546 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
    547 
    548 template <typename A, typename Functor>                   struct cwise_promote_storage_type<A,A,Functor>                                      { typedef A      ret; };
    549 template <typename Functor>                               struct cwise_promote_storage_type<Dense,Dense,Functor>                              { typedef Dense  ret; };
    550 template <typename A, typename Functor>                   struct cwise_promote_storage_type<A,Dense,Functor>                                  { typedef Dense  ret; };
    551 template <typename B, typename Functor>                   struct cwise_promote_storage_type<Dense,B,Functor>                                  { typedef Dense  ret; };
    552 template <typename Functor>                               struct cwise_promote_storage_type<Sparse,Dense,Functor>                             { typedef Sparse ret; };
    553 template <typename Functor>                               struct cwise_promote_storage_type<Dense,Sparse,Functor>                             { typedef Sparse ret; };
    554 
    555 template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order {
    556   enum { value = LhsOrder };
    557 };
    558 
    559 template <typename LhsKind, int LhsOrder, int RhsOrder>   struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder>                { enum { value = RhsOrder }; };
    560 template <typename RhsKind, int LhsOrder, int RhsOrder>   struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder>                { enum { value = LhsOrder }; };
    561 template <int Order>                                      struct cwise_promote_storage_order<Sparse,Sparse,Order,Order>                       { enum { value = Order }; };
    562 
    563 
    564 /** \internal Specify the "storage kind" of multiplying an expression of kind A with kind B.
    565   * The template parameter ProductTag permits to specialize the resulting storage kind wrt to
    566   * some compile-time properties of the product: GemmProduct, GemvProduct, OuterProduct, InnerProduct.
    567   * The default rules are as follows:
    568   * \code
    569   *  K * K            -> K
    570   *  dense * K        -> dense
    571   *  K * dense        -> dense
    572   *  diag * K         -> K
    573   *  K * diag         -> K
    574   *  Perm * K         -> K
    575   * K * Perm          -> K
    576   * \endcode
    577   */
    578 template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
    579 
    580 template <typename A, int ProductTag> struct product_promote_storage_type<A,                  A,                  ProductTag> { typedef A     ret;};
    581 template <int ProductTag>             struct product_promote_storage_type<Dense,              Dense,              ProductTag> { typedef Dense ret;};
    582 template <typename A, int ProductTag> struct product_promote_storage_type<A,                  Dense,              ProductTag> { typedef Dense ret; };
    583 template <typename B, int ProductTag> struct product_promote_storage_type<Dense,              B,                  ProductTag> { typedef Dense ret; };
    584 
    585 template <typename A, int ProductTag> struct product_promote_storage_type<A,                  DiagonalShape,      ProductTag> { typedef A ret; };
    586 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape,      B,                  ProductTag> { typedef B ret; };
    587 template <int ProductTag>             struct product_promote_storage_type<Dense,              DiagonalShape,      ProductTag> { typedef Dense ret; };
    588 template <int ProductTag>             struct product_promote_storage_type<DiagonalShape,      Dense,              ProductTag> { typedef Dense ret; };
    589 
    590 template <typename A, int ProductTag> struct product_promote_storage_type<A,                  PermutationStorage, ProductTag> { typedef A ret; };
    591 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B,                  ProductTag> { typedef B ret; };
    592 template <int ProductTag>             struct product_promote_storage_type<Dense,              PermutationStorage, ProductTag> { typedef Dense ret; };
    593 template <int ProductTag>             struct product_promote_storage_type<PermutationStorage, Dense,              ProductTag> { typedef Dense ret; };
    594 
    595 /** \internal gives the plain matrix or array type to store a row/column/diagonal of a matrix type.
    596   * \tparam Scalar optional parameter allowing to pass a different scalar type than the one of the MatrixType.
    597   */
    598 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
    599 struct plain_row_type
    600 {
    601   typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
    602                  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
    603   typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
    604                  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
    605 
    606   typedef typename conditional<
    607     is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
    608     MatrixRowType,
    609     ArrayRowType
    610   >::type type;
    611 };
    612 
    613 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
    614 struct plain_col_type
    615 {
    616   typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
    617                  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
    618   typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
    619                  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
    620 
    621   typedef typename conditional<
    622     is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
    623     MatrixColType,
    624     ArrayColType
    625   >::type type;
    626 };
    627 
    628 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
    629 struct plain_diag_type
    630 {
    631   enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
    632          max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
    633   };
    634   typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
    635   typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
    636 
    637   typedef typename conditional<
    638     is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
    639     MatrixDiagType,
    640     ArrayDiagType
    641   >::type type;
    642 };
    643 
    644 template<typename Expr,typename Scalar = typename Expr::Scalar>
    645 struct plain_constant_type
    646 {
    647   enum { Options = (traits<Expr>::Flags&RowMajorBit)?RowMajor:0 };
    648 
    649   typedef Array<Scalar,  traits<Expr>::RowsAtCompileTime,   traits<Expr>::ColsAtCompileTime,
    650                 Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> array_type;
    651 
    652   typedef Matrix<Scalar,  traits<Expr>::RowsAtCompileTime,   traits<Expr>::ColsAtCompileTime,
    653                  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> matrix_type;
    654 
    655   typedef CwiseNullaryOp<scalar_constant_op<Scalar>, const typename conditional<is_same< typename traits<Expr>::XprKind, MatrixXpr >::value, matrix_type, array_type>::type > type;
    656 };
    657 
    658 template<typename ExpressionType>
    659 struct is_lvalue
    660 {
    661   enum { value = (!bool(is_const<ExpressionType>::value)) &&
    662                  bool(traits<ExpressionType>::Flags & LvalueBit) };
    663 };
    664 
    665 template<typename T> struct is_diagonal
    666 { enum { ret = false }; };
    667 
    668 template<typename T> struct is_diagonal<DiagonalBase<T> >
    669 { enum { ret = true }; };
    670 
    671 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
    672 { enum { ret = true }; };
    673 
    674 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
    675 { enum { ret = true }; };
    676 
    677 
    678 template<typename T> struct is_identity
    679 { enum { value = false }; };
    680 
    681 template<typename T> struct is_identity<CwiseNullaryOp<internal::scalar_identity_op<typename T::Scalar>, T> >
    682 { enum { value = true }; };
    683 
    684 
    685 template<typename S1, typename S2> struct glue_shapes;
    686 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type;  };
    687 
    688 template<typename T1, typename T2>
    689 struct possibly_same_dense {
    690   enum { value = has_direct_access<T1>::ret && has_direct_access<T2>::ret && is_same<typename T1::Scalar,typename T2::Scalar>::value };
    691 };
    692 
    693 template<typename T1, typename T2>
    694 EIGEN_DEVICE_FUNC
    695 bool is_same_dense(const T1 &mat1, const T2 &mat2, typename enable_if<possibly_same_dense<T1,T2>::value>::type * = 0)
    696 {
    697   return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
    698 }
    699 
    700 template<typename T1, typename T2>
    701 EIGEN_DEVICE_FUNC
    702 bool is_same_dense(const T1 &, const T2 &, typename enable_if<!possibly_same_dense<T1,T2>::value>::type * = 0)
    703 {
    704   return false;
    705 }
    706 
    707 // Internal helper defining the cost of a scalar division for the type T.
    708 // The default heuristic can be specialized for each scalar type and architecture.
    709 template<typename T,bool Vectorized=false,typename EnableIf = void>
    710 struct scalar_div_cost {
    711   enum { value = 8*NumTraits<T>::MulCost };
    712 };
    713 
    714 template<typename T,bool Vectorized>
    715 struct scalar_div_cost<std::complex<T>, Vectorized> {
    716   enum { value = 2*scalar_div_cost<T>::value
    717                + 6*NumTraits<T>::MulCost
    718                + 3*NumTraits<T>::AddCost
    719   };
    720 };
    721 
    722 
    723 template<bool Vectorized>
    724 struct scalar_div_cost<signed long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 24 }; };
    725 template<bool Vectorized>
    726 struct scalar_div_cost<unsigned long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 21 }; };
    727 
    728 
    729 #ifdef EIGEN_DEBUG_ASSIGN
    730 std::string demangle_traversal(int t)
    731 {
    732   if(t==DefaultTraversal) return "DefaultTraversal";
    733   if(t==LinearTraversal) return "LinearTraversal";
    734   if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
    735   if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
    736   if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
    737   return "?";
    738 }
    739 std::string demangle_unrolling(int t)
    740 {
    741   if(t==NoUnrolling) return "NoUnrolling";
    742   if(t==InnerUnrolling) return "InnerUnrolling";
    743   if(t==CompleteUnrolling) return "CompleteUnrolling";
    744   return "?";
    745 }
    746 std::string demangle_flags(int f)
    747 {
    748   std::string res;
    749   if(f&RowMajorBit)                 res += " | RowMajor";
    750   if(f&PacketAccessBit)             res += " | Packet";
    751   if(f&LinearAccessBit)             res += " | Linear";
    752   if(f&LvalueBit)                   res += " | Lvalue";
    753   if(f&DirectAccessBit)             res += " | Direct";
    754   if(f&NestByRefBit)                res += " | NestByRef";
    755   if(f&NoPreferredStorageOrderBit)  res += " | NoPreferredStorageOrderBit";
    756 
    757   return res;
    758 }
    759 #endif
    760 
    761 } // end namespace internal
    762 
    763 
    764 /** \class ScalarBinaryOpTraits
    765   * \ingroup Core_Module
    766   *
    767   * \brief Determines whether the given binary operation of two numeric types is allowed and what the scalar return type is.
    768   *
    769   * This class permits to control the scalar return type of any binary operation performed on two different scalar types through (partial) template specializations.
    770   *
    771   * For instance, let \c U1, \c U2 and \c U3 be three user defined scalar types for which most operations between instances of \c U1 and \c U2 returns an \c U3.
    772   * You can let %Eigen knows that by defining:
    773     \code
    774     template<typename BinaryOp>
    775     struct ScalarBinaryOpTraits<U1,U2,BinaryOp> { typedef U3 ReturnType;  };
    776     template<typename BinaryOp>
    777     struct ScalarBinaryOpTraits<U2,U1,BinaryOp> { typedef U3 ReturnType;  };
    778     \endcode
    779   * You can then explicitly disable some particular operations to get more explicit error messages:
    780     \code
    781     template<>
    782     struct ScalarBinaryOpTraits<U1,U2,internal::scalar_max_op<U1,U2> > {};
    783     \endcode
    784   * Or customize the return type for individual operation:
    785     \code
    786     template<>
    787     struct ScalarBinaryOpTraits<U1,U2,internal::scalar_sum_op<U1,U2> > { typedef U1 ReturnType; };
    788     \endcode
    789   *
    790   * By default, the following generic combinations are supported:
    791   <table class="manual">
    792   <tr><th>ScalarA</th><th>ScalarB</th><th>BinaryOp</th><th>ReturnType</th><th>Note</th></tr>
    793   <tr            ><td>\c T </td><td>\c T </td><td>\c * </td><td>\c T </td><td></td></tr>
    794   <tr class="alt"><td>\c NumTraits<T>::Real </td><td>\c T </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
    795   <tr            ><td>\c T </td><td>\c NumTraits<T>::Real </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
    796   </table>
    797   *
    798   * \sa CwiseBinaryOp
    799   */
    800 template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
    801 struct ScalarBinaryOpTraits
    802 #ifndef EIGEN_PARSED_BY_DOXYGEN
    803   // for backward compatibility, use the hints given by the (deprecated) internal::scalar_product_traits class.
    804   : internal::scalar_product_traits<ScalarA,ScalarB>
    805 #endif // EIGEN_PARSED_BY_DOXYGEN
    806 {};
    807 
    808 template<typename T, typename BinaryOp>
    809 struct ScalarBinaryOpTraits<T,T,BinaryOp>
    810 {
    811   typedef T ReturnType;
    812 };
    813 
    814 template <typename T, typename BinaryOp>
    815 struct ScalarBinaryOpTraits<T, typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, BinaryOp>
    816 {
    817   typedef T ReturnType;
    818 };
    819 template <typename T, typename BinaryOp>
    820 struct ScalarBinaryOpTraits<typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, T, BinaryOp>
    821 {
    822   typedef T ReturnType;
    823 };
    824 
    825 // For Matrix * Permutation
    826 template<typename T, typename BinaryOp>
    827 struct ScalarBinaryOpTraits<T,void,BinaryOp>
    828 {
    829   typedef T ReturnType;
    830 };
    831 
    832 // For Permutation * Matrix
    833 template<typename T, typename BinaryOp>
    834 struct ScalarBinaryOpTraits<void,T,BinaryOp>
    835 {
    836   typedef T ReturnType;
    837 };
    838 
    839 // for Permutation*Permutation
    840 template<typename BinaryOp>
    841 struct ScalarBinaryOpTraits<void,void,BinaryOp>
    842 {
    843   typedef void ReturnType;
    844 };
    845 
    846 // We require Lhs and Rhs to have "compatible" scalar types.
    847 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
    848 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
    849 // add together a float matrix and a double matrix.
    850 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
    851   EIGEN_STATIC_ASSERT((Eigen::internal::has_ReturnType<ScalarBinaryOpTraits<LHS, RHS,BINOP> >::value), \
    852     YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
    853 
    854 } // end namespace Eigen
    855 
    856 #endif // EIGEN_XPRHELPER_H