Eigen  3.3.7
XprHelper.h
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 
38 // promote_scalar_arg is an helper used in operation between an expression and a scalar, like:
39 // expression * scalar
40 // 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.
41 // 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.
42 // Then the logic is as follows:
43 // - if the operation is natively supported as defined by IsSupported, then the scalar type is not promoted, and T is returned.
44 // - 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.
45 // - otherwise, ExprScalar is returned if T is implicitly convertible to ExprScalar AND that this does not imply a float to integer conversion.
46 // - In all other cases, the promoted type is not defined, and the respective operation is thus invalid and not available (SFINAE).
47 template<typename ExprScalar,typename T, bool IsSupported>
48 struct promote_scalar_arg;
49 
50 template<typename S,typename T>
51 struct promote_scalar_arg<S,T,true>
52 {
53  typedef T type;
54 };
55 
56 // Recursively check safe conversion to PromotedType, and then ExprScalar if they are different.
57 template<typename ExprScalar,typename T,typename PromotedType,
58  bool ConvertibleToLiteral = internal::is_convertible<T,PromotedType>::value,
59  bool IsSafe = NumTraits<T>::IsInteger || !NumTraits<PromotedType>::IsInteger>
60 struct promote_scalar_arg_unsupported;
61 
62 // Start recursion with NumTraits<ExprScalar>::Literal
63 template<typename S,typename T>
64 struct promote_scalar_arg<S,T,false> : promote_scalar_arg_unsupported<S,T,typename NumTraits<S>::Literal> {};
65 
66 // We found a match!
67 template<typename S,typename T, typename PromotedType>
68 struct promote_scalar_arg_unsupported<S,T,PromotedType,true,true>
69 {
70  typedef PromotedType type;
71 };
72 
73 // No match, but no real-to-integer issues, and ExprScalar and current PromotedType are different,
74 // so let's try to promote to ExprScalar
75 template<typename ExprScalar,typename T, typename PromotedType>
76 struct promote_scalar_arg_unsupported<ExprScalar,T,PromotedType,false,true>
77  : promote_scalar_arg_unsupported<ExprScalar,T,ExprScalar>
78 {};
79 
80 // Unsafe real-to-integer, let's stop.
81 template<typename S,typename T, typename PromotedType, bool ConvertibleToLiteral>
82 struct promote_scalar_arg_unsupported<S,T,PromotedType,ConvertibleToLiteral,false> {};
83 
84 // T is not even convertible to ExprScalar, let's stop.
85 template<typename S,typename T>
86 struct promote_scalar_arg_unsupported<S,T,S,false,true> {};
87 
88 //classes inheriting no_assignment_operator don't generate a default operator=.
89 class no_assignment_operator
90 {
91  private:
92  no_assignment_operator& operator=(const no_assignment_operator&);
93  protected:
94  EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator)
95  EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator)
96 };
97 
99 template<typename I1, typename I2>
100 struct promote_index_type
101 {
102  typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
103 };
104 
109 template<typename T, int Value> class variable_if_dynamic
110 {
111  public:
112  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
113  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
114  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T value() { return T(Value); }
115  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T) {}
116 };
117 
118 template<typename T> class variable_if_dynamic<T, Dynamic>
119 {
120  T m_value;
121  EIGEN_DEVICE_FUNC variable_if_dynamic() { eigen_assert(false); }
122  public:
123  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value) : m_value(value) {}
124  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; }
125  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
126 };
127 
130 template<typename T, int Value> class variable_if_dynamicindex
131 {
132  public:
133  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex)
134  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
135  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T value() { return T(Value); }
136  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T) {}
137 };
138 
139 template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
140 {
141  T m_value;
142  EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
143  public:
144  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T value) : m_value(value) {}
145  EIGEN_DEVICE_FUNC T EIGEN_STRONG_INLINE value() const { return m_value; }
146  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
147 };
148 
149 template<typename T> struct functor_traits
150 {
151  enum
152  {
153  Cost = 10,
154  PacketAccess = false,
155  IsRepeatable = false
156  };
157 };
158 
159 template<typename T> struct packet_traits;
160 
161 template<typename T> struct unpacket_traits
162 {
163  typedef T type;
164  typedef T half;
165  enum
166  {
167  size = 1,
168  alignment = 1
169  };
170 };
171 
172 template<int Size, typename PacketType,
173  bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
174 struct find_best_packet_helper;
175 
176 template< int Size, typename PacketType>
177 struct find_best_packet_helper<Size,PacketType,true>
178 {
179  typedef PacketType type;
180 };
181 
182 template<int Size, typename PacketType>
183 struct find_best_packet_helper<Size,PacketType,false>
184 {
185  typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
186 };
187 
188 template<typename T, int Size>
189 struct find_best_packet
190 {
191  typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
192 };
193 
194 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
195 template<int ArrayBytes, int AlignmentBytes,
196  bool Match = bool((ArrayBytes%AlignmentBytes)==0),
197  bool TryHalf = bool(EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) >
198 struct compute_default_alignment_helper
199 {
200  enum { value = 0 };
201 };
202 
203 template<int ArrayBytes, int AlignmentBytes, bool TryHalf>
204 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, true, TryHalf> // Match
205 {
206  enum { value = AlignmentBytes };
207 };
208 
209 template<int ArrayBytes, int AlignmentBytes>
210 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, false, true> // Try-half
211 {
212  // current packet too large, try with an half-packet
213  enum { value = compute_default_alignment_helper<ArrayBytes, AlignmentBytes/2>::value };
214 };
215 #else
216 // If static alignment is disabled, no need to bother.
217 // This also avoids a division by zero in "bool Match = bool((ArrayBytes%AlignmentBytes)==0)"
218 template<int ArrayBytes, int AlignmentBytes>
219 struct compute_default_alignment_helper
220 {
221  enum { value = 0 };
222 };
223 #endif
224 
225 template<typename T, int Size> struct compute_default_alignment {
226  enum { value = compute_default_alignment_helper<Size*sizeof(T),EIGEN_MAX_STATIC_ALIGN_BYTES>::value };
227 };
228 
229 template<typename T> struct compute_default_alignment<T,Dynamic> {
230  enum { value = EIGEN_MAX_ALIGN_BYTES };
231 };
232 
233 template<typename _Scalar, int _Rows, int _Cols,
234  int _Options = AutoAlign |
235  ( (_Rows==1 && _Cols!=1) ? RowMajor
236  : (_Cols==1 && _Rows!=1) ? ColMajor
237  : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
238  int _MaxRows = _Rows,
239  int _MaxCols = _Cols
240 > class make_proper_matrix_type
241 {
242  enum {
243  IsColVector = _Cols==1 && _Rows!=1,
244  IsRowVector = _Rows==1 && _Cols!=1,
245  Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
246  : IsRowVector ? (_Options | RowMajor) & ~ColMajor
247  : _Options
248  };
249  public:
250  typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
251 };
252 
253 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
254 class compute_matrix_flags
255 {
256  enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 };
257  public:
258  // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
259  // and then propagate this information to the evaluator's flags.
260  // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
261  enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit };
262 };
263 
264 template<int _Rows, int _Cols> struct size_at_compile_time
265 {
266  enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
267 };
268 
269 template<typename XprType> struct size_of_xpr_at_compile_time
270 {
271  enum { ret = size_at_compile_time<traits<XprType>::RowsAtCompileTime,traits<XprType>::ColsAtCompileTime>::ret };
272 };
273 
274 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
275  * whereas eval is a const reference in the case of a matrix
276  */
277 
278 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
279 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
280 template<typename T> struct plain_matrix_type<T,Dense>
281 {
282  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
283 };
284 template<typename T> struct plain_matrix_type<T,DiagonalShape>
285 {
286  typedef typename T::PlainObject type;
287 };
288 
289 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
290 {
291  typedef Matrix<typename traits<T>::Scalar,
292  traits<T>::RowsAtCompileTime,
293  traits<T>::ColsAtCompileTime,
294  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
295  traits<T>::MaxRowsAtCompileTime,
296  traits<T>::MaxColsAtCompileTime
297  > type;
298 };
299 
300 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
301 {
302  typedef Array<typename traits<T>::Scalar,
303  traits<T>::RowsAtCompileTime,
304  traits<T>::ColsAtCompileTime,
305  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
306  traits<T>::MaxRowsAtCompileTime,
307  traits<T>::MaxColsAtCompileTime
308  > type;
309 };
310 
311 /* eval : the return type of eval(). For matrices, this is just a const reference
312  * in order to avoid a useless copy
313  */
314 
315 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
316 
317 template<typename T> struct eval<T,Dense>
318 {
319  typedef typename plain_matrix_type<T>::type type;
320 // typedef typename T::PlainObject type;
321 // typedef T::Matrix<typename traits<T>::Scalar,
322 // traits<T>::RowsAtCompileTime,
323 // traits<T>::ColsAtCompileTime,
324 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
325 // traits<T>::MaxRowsAtCompileTime,
326 // traits<T>::MaxColsAtCompileTime
327 // > type;
328 };
329 
330 template<typename T> struct eval<T,DiagonalShape>
331 {
332  typedef typename plain_matrix_type<T>::type type;
333 };
334 
335 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
336 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
337 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
338 {
339  typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
340 };
341 
342 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
343 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
344 {
345  typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
346 };
347 
348 
349 /* similar to plain_matrix_type, but using the evaluator's Flags */
350 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
351 
352 template<typename T>
353 struct plain_object_eval<T,Dense>
354 {
355  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
356 };
357 
358 
359 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
360  */
361 template<typename T> struct plain_matrix_type_column_major
362 {
363  enum { Rows = traits<T>::RowsAtCompileTime,
364  Cols = traits<T>::ColsAtCompileTime,
365  MaxRows = traits<T>::MaxRowsAtCompileTime,
366  MaxCols = traits<T>::MaxColsAtCompileTime
367  };
368  typedef Matrix<typename traits<T>::Scalar,
369  Rows,
370  Cols,
371  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
372  MaxRows,
373  MaxCols
374  > type;
375 };
376 
377 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
378  */
379 template<typename T> struct plain_matrix_type_row_major
380 {
381  enum { Rows = traits<T>::RowsAtCompileTime,
382  Cols = traits<T>::ColsAtCompileTime,
383  MaxRows = traits<T>::MaxRowsAtCompileTime,
384  MaxCols = traits<T>::MaxColsAtCompileTime
385  };
386  typedef Matrix<typename traits<T>::Scalar,
387  Rows,
388  Cols,
389  (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
390  MaxRows,
391  MaxCols
392  > type;
393 };
394 
398 template <typename T>
399 struct ref_selector
400 {
401  typedef typename conditional<
402  bool(traits<T>::Flags & NestByRefBit),
403  T const&,
404  const T
405  >::type type;
406 
407  typedef typename conditional<
408  bool(traits<T>::Flags & NestByRefBit),
409  T &,
410  T
411  >::type non_const_type;
412 };
413 
415 template<typename T1, typename T2>
416 struct transfer_constness
417 {
418  typedef typename conditional<
419  bool(internal::is_const<T1>::value),
420  typename internal::add_const_on_value_type<T2>::type,
421  T2
422  >::type type;
423 };
424 
425 
426 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time
427 // has to be evaluated into a temporary.
428 // That's the purpose of this new nested_eval helper:
440 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
441 {
442  enum {
443  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
444  CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory?
445  // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
446  // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
447  // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
448  // Another solution could be to count the number of temps?
449  NAsInteger = n == Dynamic ? HugeCost : n,
450  CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
451  CostNoEval = NAsInteger * CoeffReadCost,
452  Evaluate = (int(evaluator<T>::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval))
453  };
454 
455  typedef typename conditional<Evaluate, PlainObject, typename ref_selector<T>::type>::type type;
456 };
457 
458 template<typename T>
459 EIGEN_DEVICE_FUNC
460 inline T* const_cast_ptr(const T* ptr)
461 {
462  return const_cast<T*>(ptr);
463 }
464 
465 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
466 struct dense_xpr_base
467 {
468  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
469 };
470 
471 template<typename Derived>
472 struct dense_xpr_base<Derived, MatrixXpr>
473 {
474  typedef MatrixBase<Derived> type;
475 };
476 
477 template<typename Derived>
478 struct dense_xpr_base<Derived, ArrayXpr>
479 {
480  typedef ArrayBase<Derived> type;
481 };
482 
483 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
484 struct generic_xpr_base;
485 
486 template<typename Derived, typename XprKind>
487 struct generic_xpr_base<Derived, XprKind, Dense>
488 {
489  typedef typename dense_xpr_base<Derived,XprKind>::type type;
490 };
491 
492 template<typename XprType, typename CastType> struct cast_return_type
493 {
494  typedef typename XprType::Scalar CurrentScalarType;
495  typedef typename remove_all<CastType>::type _CastType;
496  typedef typename _CastType::Scalar NewScalarType;
497  typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
498  const XprType&,CastType>::type type;
499 };
500 
501 template <typename A, typename B> struct promote_storage_type;
502 
503 template <typename A> struct promote_storage_type<A,A>
504 {
505  typedef A ret;
506 };
507 template <typename A> struct promote_storage_type<A, const A>
508 {
509  typedef A ret;
510 };
511 template <typename A> struct promote_storage_type<const A, A>
512 {
513  typedef A ret;
514 };
515 
529 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
530 
531 template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; };
532 template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; };
533 template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; };
534 template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; };
535 template <typename Functor> struct cwise_promote_storage_type<Sparse,Dense,Functor> { typedef Sparse ret; };
536 template <typename Functor> struct cwise_promote_storage_type<Dense,Sparse,Functor> { typedef Sparse ret; };
537 
538 template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order {
539  enum { value = LhsOrder };
540 };
541 
542 template <typename LhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder> { enum { value = RhsOrder }; };
543 template <typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder> { enum { value = LhsOrder }; };
544 template <int Order> struct cwise_promote_storage_order<Sparse,Sparse,Order,Order> { enum { value = Order }; };
545 
546 
561 template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
562 
563 template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;};
564 template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;};
565 template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; };
566 template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; };
567 
568 template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; };
569 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; };
570 template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; };
571 template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; };
572 
573 template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; };
574 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; };
575 template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; };
576 template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; };
577 
581 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
582 struct plain_row_type
583 {
584  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
585  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
586  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
587  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
588 
589  typedef typename conditional<
590  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
591  MatrixRowType,
592  ArrayRowType
593  >::type type;
594 };
595 
596 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
597 struct plain_col_type
598 {
599  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
600  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
601  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
602  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
603 
604  typedef typename conditional<
605  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
606  MatrixColType,
607  ArrayColType
608  >::type type;
609 };
610 
611 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
612 struct plain_diag_type
613 {
614  enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
615  max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
616  };
617  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
618  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
619 
620  typedef typename conditional<
621  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
622  MatrixDiagType,
623  ArrayDiagType
624  >::type type;
625 };
626 
627 template<typename Expr,typename Scalar = typename Expr::Scalar>
628 struct plain_constant_type
629 {
630  enum { Options = (traits<Expr>::Flags&RowMajorBit)?RowMajor:0 };
631 
632  typedef Array<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
633  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> array_type;
634 
635  typedef Matrix<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
636  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> matrix_type;
637 
638  typedef CwiseNullaryOp<scalar_constant_op<Scalar>, const typename conditional<is_same< typename traits<Expr>::XprKind, MatrixXpr >::value, matrix_type, array_type>::type > type;
639 };
640 
641 template<typename ExpressionType>
642 struct is_lvalue
643 {
644  enum { value = (!bool(is_const<ExpressionType>::value)) &&
645  bool(traits<ExpressionType>::Flags & LvalueBit) };
646 };
647 
648 template<typename T> struct is_diagonal
649 { enum { ret = false }; };
650 
651 template<typename T> struct is_diagonal<DiagonalBase<T> >
652 { enum { ret = true }; };
653 
654 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
655 { enum { ret = true }; };
656 
657 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
658 { enum { ret = true }; };
659 
660 template<typename S1, typename S2> struct glue_shapes;
661 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; };
662 
663 template<typename T1, typename T2>
664 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)
665 {
666  return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
667 }
668 
669 template<typename T1, typename T2>
670 bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_access<T1>::ret&&has_direct_access<T2>::ret), T1>::type * = 0)
671 {
672  return false;
673 }
674 
675 // Internal helper defining the cost of a scalar division for the type T.
676 // The default heuristic can be specialized for each scalar type and architecture.
677 template<typename T,bool Vectorized=false,typename EnaleIf = void>
678 struct scalar_div_cost {
679  enum { value = 8*NumTraits<T>::MulCost };
680 };
681 
682 template<typename T,bool Vectorized>
683 struct scalar_div_cost<std::complex<T>, Vectorized> {
684  enum { value = 2*scalar_div_cost<T>::value
685  + 6*NumTraits<T>::MulCost
686  + 3*NumTraits<T>::AddCost
687  };
688 };
689 
690 
691 template<bool Vectorized>
692 struct scalar_div_cost<signed long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 24 }; };
693 template<bool Vectorized>
694 struct scalar_div_cost<unsigned long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 21 }; };
695 
696 
697 #ifdef EIGEN_DEBUG_ASSIGN
698 std::string demangle_traversal(int t)
699 {
700  if(t==DefaultTraversal) return "DefaultTraversal";
701  if(t==LinearTraversal) return "LinearTraversal";
702  if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
703  if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
704  if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
705  return "?";
706 }
707 std::string demangle_unrolling(int t)
708 {
709  if(t==NoUnrolling) return "NoUnrolling";
710  if(t==InnerUnrolling) return "InnerUnrolling";
711  if(t==CompleteUnrolling) return "CompleteUnrolling";
712  return "?";
713 }
714 std::string demangle_flags(int f)
715 {
716  std::string res;
717  if(f&RowMajorBit) res += " | RowMajor";
718  if(f&PacketAccessBit) res += " | Packet";
719  if(f&LinearAccessBit) res += " | Linear";
720  if(f&LvalueBit) res += " | Lvalue";
721  if(f&DirectAccessBit) res += " | Direct";
722  if(f&NestByRefBit) res += " | NestByRef";
723  if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit";
724 
725  return res;
726 }
727 #endif
728 
729 } // end namespace internal
730 
731 
768 template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
770 #ifndef EIGEN_PARSED_BY_DOXYGEN
771  // for backward compatibility, use the hints given by the (deprecated) internal::scalar_product_traits class.
772  : internal::scalar_product_traits<ScalarA,ScalarB>
773 #endif // EIGEN_PARSED_BY_DOXYGEN
774 {};
775 
776 template<typename T, typename BinaryOp>
777 struct ScalarBinaryOpTraits<T,T,BinaryOp>
778 {
779  typedef T ReturnType;
780 };
781 
782 template <typename T, typename BinaryOp>
783 struct ScalarBinaryOpTraits<T, typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, BinaryOp>
784 {
785  typedef T ReturnType;
786 };
787 template <typename T, typename BinaryOp>
788 struct ScalarBinaryOpTraits<typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, T, BinaryOp>
789 {
790  typedef T ReturnType;
791 };
792 
793 // For Matrix * Permutation
794 template<typename T, typename BinaryOp>
795 struct ScalarBinaryOpTraits<T,void,BinaryOp>
796 {
797  typedef T ReturnType;
798 };
799 
800 // For Permutation * Matrix
801 template<typename T, typename BinaryOp>
802 struct ScalarBinaryOpTraits<void,T,BinaryOp>
803 {
804  typedef T ReturnType;
805 };
806 
807 // for Permutation*Permutation
808 template<typename BinaryOp>
809 struct ScalarBinaryOpTraits<void,void,BinaryOp>
810 {
811  typedef void ReturnType;
812 };
813 
814 // We require Lhs and Rhs to have "compatible" scalar types.
815 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
816 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
817 // add together a float matrix and a double matrix.
818 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
819  EIGEN_STATIC_ASSERT((Eigen::internal::has_ReturnType<ScalarBinaryOpTraits<LHS, RHS,BINOP> >::value), \
820  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
821 
822 } // end namespace Eigen
823 
824 #endif // EIGEN_XPRHELPER_H
Eigen::HugeCost
const int HugeCost
Definition: Constants.h:39
Eigen
Namespace containing all symbols from the Eigen library.
Definition: Core:306
Eigen::RowMajorBit
const unsigned int RowMajorBit
Definition: Constants.h:61
Eigen::ScalarBinaryOpTraits
Determines whether the given binary operation of two numeric types is allowed and what the scalar ret...
Definition: XprHelper.h:769
Eigen::RowMajor
@ RowMajor
Definition: Constants.h:322
Eigen::DirectAccessBit
const unsigned int DirectAccessBit
Definition: Constants.h:150
Eigen::PacketAccessBit
const unsigned int PacketAccessBit
Definition: Constants.h:89
Eigen::LvalueBit
const unsigned int LvalueBit
Definition: Constants.h:139
Eigen::Dynamic
const int Dynamic
Definition: Constants.h:21
Eigen::AutoAlign
@ AutoAlign
Definition: Constants.h:324
Eigen::LinearAccessBit
const unsigned int LinearAccessBit
Definition: Constants.h:125
Eigen::DenseBase::RowsAtCompileTime
@ RowsAtCompileTime
Definition: DenseBase.h:100
Eigen::DynamicIndex
const int DynamicIndex
Definition: Constants.h:26
Eigen::ColMajor
@ ColMajor
Definition: Constants.h:320
Eigen::NoPreferredStorageOrderBit
const unsigned int NoPreferredStorageOrderBit
Definition: Constants.h:173
Eigen::EvalBeforeNestingBit
const unsigned int EvalBeforeNestingBit
Definition: Constants.h:65