Eigen  3.2.92
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 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
28 
35 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
36 
37 namespace internal {
38 
39 template<typename IndexDest, typename IndexSrc>
40 EIGEN_DEVICE_FUNC
41 inline IndexDest convert_index(const IndexSrc& idx) {
42  // for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away:
43  eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value to big for target type");
44  return IndexDest(idx);
45 }
46 
47 
48 //classes inheriting no_assignment_operator don't generate a default operator=.
49 class no_assignment_operator
50 {
51  private:
52  no_assignment_operator& operator=(const no_assignment_operator&);
53 };
54 
56 template<typename I1, typename I2>
57 struct promote_index_type
58 {
59  typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
60 };
61 
66 template<typename T, int Value> class variable_if_dynamic
67 {
68  public:
69  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
70  EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
71  EIGEN_DEVICE_FUNC static T value() { return T(Value); }
72  EIGEN_DEVICE_FUNC void setValue(T) {}
73 };
74 
75 template<typename T> class variable_if_dynamic<T, Dynamic>
76 {
77  T m_value;
78  EIGEN_DEVICE_FUNC variable_if_dynamic() { eigen_assert(false); }
79  public:
80  EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T value) : m_value(value) {}
81  EIGEN_DEVICE_FUNC T value() const { return m_value; }
82  EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; }
83 };
84 
87 template<typename T, int Value> class variable_if_dynamicindex
88 {
89  public:
90  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex)
91  EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
92  EIGEN_DEVICE_FUNC static T value() { return T(Value); }
93  EIGEN_DEVICE_FUNC void setValue(T) {}
94 };
95 
96 template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
97 {
98  T m_value;
99  EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
100  public:
101  EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T value) : m_value(value) {}
102  EIGEN_DEVICE_FUNC T value() const { return m_value; }
103  EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; }
104 };
105 
106 template<typename T> struct functor_traits
107 {
108  enum
109  {
110  Cost = 10,
111  PacketAccess = false,
112  IsRepeatable = false
113  };
114 };
115 
116 template<typename T> struct packet_traits;
117 
118 template<typename T> struct unpacket_traits
119 {
120  typedef T type;
121  typedef T half;
122  enum
123  {
124  size = 1,
125  alignment = 1
126  };
127 };
128 
129 template<int Size, typename PacketType,
130  bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
131 struct find_best_packet_helper;
132 
133 template< int Size, typename PacketType>
134 struct find_best_packet_helper<Size,PacketType,true>
135 {
136  typedef PacketType type;
137 };
138 
139 template<int Size, typename PacketType>
140 struct find_best_packet_helper<Size,PacketType,false>
141 {
142  typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
143 };
144 
145 template<typename T, int Size>
146 struct find_best_packet
147 {
148  typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
149 };
150 
151 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
152 template<int ArrayBytes, int AlignmentBytes,
153  bool Match = bool((ArrayBytes%AlignmentBytes)==0),
154  bool TryHalf = bool(AlignmentBytes>EIGEN_MIN_ALIGN_BYTES) >
155 struct compute_default_alignment_helper
156 {
157  enum { value = 0 };
158 };
159 
160 template<int ArrayBytes, int AlignmentBytes, bool TryHalf>
161 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, true, TryHalf> // Match
162 {
163  enum { value = AlignmentBytes };
164 };
165 
166 template<int ArrayBytes, int AlignmentBytes>
167 struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, false, true> // Try-half
168 {
169  // current packet too large, try with an half-packet
170  enum { value = compute_default_alignment_helper<ArrayBytes, AlignmentBytes/2>::value };
171 };
172 #else
173 // If static alignment is disabled, no need to bother.
174 // This also avoids a division by zero in "bool Match = bool((ArrayBytes%AlignmentBytes)==0)"
175 template<int ArrayBytes, int AlignmentBytes>
176 struct compute_default_alignment_helper
177 {
178  enum { value = 0 };
179 };
180 #endif
181 
182 template<typename T, int Size> struct compute_default_alignment {
183  enum { value = compute_default_alignment_helper<Size*sizeof(T),EIGEN_MAX_STATIC_ALIGN_BYTES>::value };
184 };
185 
186 template<typename T> struct compute_default_alignment<T,Dynamic> {
187  enum { value = EIGEN_MAX_ALIGN_BYTES };
188 };
189 
190 template<typename _Scalar, int _Rows, int _Cols,
191  int _Options = AutoAlign |
192  ( (_Rows==1 && _Cols!=1) ? RowMajor
193  : (_Cols==1 && _Rows!=1) ? ColMajor
194  : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
195  int _MaxRows = _Rows,
196  int _MaxCols = _Cols
197 > class make_proper_matrix_type
198 {
199  enum {
200  IsColVector = _Cols==1 && _Rows!=1,
201  IsRowVector = _Rows==1 && _Cols!=1,
202  Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
203  : IsRowVector ? (_Options | RowMajor) & ~ColMajor
204  : _Options
205  };
206  public:
207  typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
208 };
209 
210 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
211 class compute_matrix_flags
212 {
213  enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 };
214  public:
215  // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
216  // and then propagate this information to the evaluator's flags.
217  // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
218  enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit };
219 };
220 
221 template<int _Rows, int _Cols> struct size_at_compile_time
222 {
223  enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
224 };
225 
226 template<typename XprType> struct size_of_xpr_at_compile_time
227 {
228  enum { ret = size_at_compile_time<traits<XprType>::RowsAtCompileTime,traits<XprType>::ColsAtCompileTime>::ret };
229 };
230 
231 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
232  * whereas eval is a const reference in the case of a matrix
233  */
234 
235 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
236 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
237 template<typename T> struct plain_matrix_type<T,Dense>
238 {
239  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
240 };
241 template<typename T> struct plain_matrix_type<T,DiagonalShape>
242 {
243  typedef typename T::PlainObject type;
244 };
245 
246 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
247 {
248  typedef Matrix<typename traits<T>::Scalar,
249  traits<T>::RowsAtCompileTime,
250  traits<T>::ColsAtCompileTime,
251  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
252  traits<T>::MaxRowsAtCompileTime,
253  traits<T>::MaxColsAtCompileTime
254  > type;
255 };
256 
257 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
258 {
259  typedef Array<typename traits<T>::Scalar,
260  traits<T>::RowsAtCompileTime,
261  traits<T>::ColsAtCompileTime,
262  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
263  traits<T>::MaxRowsAtCompileTime,
264  traits<T>::MaxColsAtCompileTime
265  > type;
266 };
267 
268 /* eval : the return type of eval(). For matrices, this is just a const reference
269  * in order to avoid a useless copy
270  */
271 
272 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
273 
274 template<typename T> struct eval<T,Dense>
275 {
276  typedef typename plain_matrix_type<T>::type type;
277 // typedef typename T::PlainObject type;
278 // typedef T::Matrix<typename traits<T>::Scalar,
279 // traits<T>::RowsAtCompileTime,
280 // traits<T>::ColsAtCompileTime,
281 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
282 // traits<T>::MaxRowsAtCompileTime,
283 // traits<T>::MaxColsAtCompileTime
284 // > type;
285 };
286 
287 template<typename T> struct eval<T,DiagonalShape>
288 {
289  typedef typename plain_matrix_type<T>::type type;
290 };
291 
292 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
293 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
294 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
295 {
296  typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
297 };
298 
299 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
300 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
301 {
302  typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
303 };
304 
305 
306 /* similar to plain_matrix_type, but using the evaluator's Flags */
307 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
308 
309 template<typename T>
310 struct plain_object_eval<T,Dense>
311 {
312  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
313 };
314 
315 
316 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
317  */
318 template<typename T> struct plain_matrix_type_column_major
319 {
320  enum { Rows = traits<T>::RowsAtCompileTime,
321  Cols = traits<T>::ColsAtCompileTime,
322  MaxRows = traits<T>::MaxRowsAtCompileTime,
323  MaxCols = traits<T>::MaxColsAtCompileTime
324  };
325  typedef Matrix<typename traits<T>::Scalar,
326  Rows,
327  Cols,
328  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
329  MaxRows,
330  MaxCols
331  > type;
332 };
333 
334 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
335  */
336 template<typename T> struct plain_matrix_type_row_major
337 {
338  enum { Rows = traits<T>::RowsAtCompileTime,
339  Cols = traits<T>::ColsAtCompileTime,
340  MaxRows = traits<T>::MaxRowsAtCompileTime,
341  MaxCols = traits<T>::MaxColsAtCompileTime
342  };
343  typedef Matrix<typename traits<T>::Scalar,
344  Rows,
345  Cols,
346  (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
347  MaxRows,
348  MaxCols
349  > type;
350 };
351 
355 template <typename T>
356 struct ref_selector
357 {
358  typedef typename conditional<
359  bool(traits<T>::Flags & NestByRefBit),
360  T const&,
361  const T
362  >::type type;
363 
364  typedef typename conditional<
365  bool(traits<T>::Flags & NestByRefBit),
366  T &,
367  T
368  >::type non_const_type;
369 };
370 
372 template<typename T1, typename T2>
373 struct transfer_constness
374 {
375  typedef typename conditional<
376  bool(internal::is_const<T1>::value),
377  typename internal::add_const_on_value_type<T2>::type,
378  T2
379  >::type type;
380 };
381 
382 
383 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time
384 // has to be evaluated into a temporary.
385 // That's the purpose of this new nested_eval helper:
397 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
398 {
399  enum {
400  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
401  CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory?
402  // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
403  // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
404  // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
405  // Another solution could be to count the number of temps?
406  NAsInteger = n == Dynamic ? HugeCost : n,
407  CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
408  CostNoEval = NAsInteger * CoeffReadCost
409  };
410 
411  typedef typename conditional<
412  ( (int(evaluator<T>::Flags) & EvalBeforeNestingBit) ||
413  (int(CostEval) < int(CostNoEval)) ),
414  PlainObject,
415  typename ref_selector<T>::type
416  >::type type;
417 };
418 
419 template<typename T>
420 EIGEN_DEVICE_FUNC
421 inline T* const_cast_ptr(const T* ptr)
422 {
423  return const_cast<T*>(ptr);
424 }
425 
426 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
427 struct dense_xpr_base
428 {
429  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
430 };
431 
432 template<typename Derived>
433 struct dense_xpr_base<Derived, MatrixXpr>
434 {
435  typedef MatrixBase<Derived> type;
436 };
437 
438 template<typename Derived>
439 struct dense_xpr_base<Derived, ArrayXpr>
440 {
441  typedef ArrayBase<Derived> type;
442 };
443 
444 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
445 struct generic_xpr_base;
446 
447 template<typename Derived, typename XprKind>
448 struct generic_xpr_base<Derived, XprKind, Dense>
449 {
450  typedef typename dense_xpr_base<Derived,XprKind>::type type;
451 };
452 
455 template<typename Derived, typename Scalar, typename OtherScalar, typename BaseType,
456  bool EnableIt = !is_same<Scalar,OtherScalar>::value >
457 struct special_scalar_op_base : public BaseType
458 {
459  // dummy operator* so that the
460  // "using special_scalar_op_base::operator*" compiles
461  struct dummy {};
462  void operator*(dummy) const;
463  void operator/(dummy) const;
464 };
465 
466 template<typename Derived,typename Scalar,typename OtherScalar, typename BaseType>
467 struct special_scalar_op_base<Derived,Scalar,OtherScalar,BaseType,true> : public BaseType
468 {
469  const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
470  operator*(const OtherScalar& scalar) const
471  {
472 #ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
473  EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
474 #endif
475  return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
476  (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar));
477  }
478 
479  inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
480  operator*(const OtherScalar& scalar, const Derived& matrix)
481  {
482 #ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
483  EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
484 #endif
485  return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar);
486  }
487 
488  const CwiseUnaryOp<scalar_quotient2_op<Scalar,OtherScalar>, Derived>
489  operator/(const OtherScalar& scalar) const
490  {
491 #ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
492  EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
493 #endif
494  return CwiseUnaryOp<scalar_quotient2_op<Scalar,OtherScalar>, Derived>
495  (*static_cast<const Derived*>(this), scalar_quotient2_op<Scalar,OtherScalar>(scalar));
496  }
497 };
498 
499 template<typename XprType, typename CastType> struct cast_return_type
500 {
501  typedef typename XprType::Scalar CurrentScalarType;
502  typedef typename remove_all<CastType>::type _CastType;
503  typedef typename _CastType::Scalar NewScalarType;
504  typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
505  const XprType&,CastType>::type type;
506 };
507 
508 template <typename A, typename B> struct promote_storage_type;
509 
510 template <typename A> struct promote_storage_type<A,A>
511 {
512  typedef A ret;
513 };
514 template <typename A> struct promote_storage_type<A, const A>
515 {
516  typedef A ret;
517 };
518 template <typename A> struct promote_storage_type<const A, A>
519 {
520  typedef A ret;
521 };
522 
536 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
537 
538 template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; };
539 template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; };
540 template <typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<Dense,Dense,scalar_product_op<ScalarA,ScalarB> > { typedef Dense ret; };
541 template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; };
542 template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; };
543 template <typename A, typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<A,Dense,scalar_product_op<ScalarA,ScalarB> > { typedef A ret; };
544 template <typename B, typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<Dense,B,scalar_product_op<ScalarA,ScalarB> > { typedef B ret; };
545 
560 template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
561 
562 template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;};
563 template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;};
564 template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; };
565 template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; };
566 
567 template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; };
568 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; };
569 template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; };
570 template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; };
571 
572 template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; };
573 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; };
574 template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; };
575 template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; };
576 
580 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
581 struct plain_row_type
582 {
583  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
584  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
585  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
586  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
587 
588  typedef typename conditional<
589  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
590  MatrixRowType,
591  ArrayRowType
592  >::type type;
593 };
594 
595 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
596 struct plain_col_type
597 {
598  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
599  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
600  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
601  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
602 
603  typedef typename conditional<
604  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
605  MatrixColType,
606  ArrayColType
607  >::type type;
608 };
609 
610 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
611 struct plain_diag_type
612 {
613  enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
614  max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
615  };
616  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
617  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
618 
619  typedef typename conditional<
620  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
621  MatrixDiagType,
622  ArrayDiagType
623  >::type type;
624 };
625 
626 template<typename ExpressionType>
627 struct is_lvalue
628 {
629  enum { value = !bool(is_const<ExpressionType>::value) &&
630  bool(traits<ExpressionType>::Flags & LvalueBit) };
631 };
632 
633 template<typename T> struct is_diagonal
634 { enum { ret = false }; };
635 
636 template<typename T> struct is_diagonal<DiagonalBase<T> >
637 { enum { ret = true }; };
638 
639 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
640 { enum { ret = true }; };
641 
642 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
643 { enum { ret = true }; };
644 
645 template<typename S1, typename S2> struct glue_shapes;
646 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; };
647 
648 template<typename T1, typename T2>
649 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)
650 {
651  return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
652 }
653 
654 template<typename T1, typename T2>
655 bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_access<T1>::ret&&has_direct_access<T2>::ret), T1>::type * = 0)
656 {
657  return false;
658 }
659 
660 template<typename T, typename U> struct is_same_or_void { enum { value = is_same<T,U>::value }; };
661 template<typename T> struct is_same_or_void<void,T> { enum { value = 1 }; };
662 template<typename T> struct is_same_or_void<T,void> { enum { value = 1 }; };
663 template<> struct is_same_or_void<void,void> { enum { value = 1 }; };
664 
665 #ifdef EIGEN_DEBUG_ASSIGN
666 std::string demangle_traversal(int t)
667 {
668  if(t==DefaultTraversal) return "DefaultTraversal";
669  if(t==LinearTraversal) return "LinearTraversal";
670  if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
671  if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
672  if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
673  return "?";
674 }
675 std::string demangle_unrolling(int t)
676 {
677  if(t==NoUnrolling) return "NoUnrolling";
678  if(t==InnerUnrolling) return "InnerUnrolling";
679  if(t==CompleteUnrolling) return "CompleteUnrolling";
680  return "?";
681 }
682 std::string demangle_flags(int f)
683 {
684  std::string res;
685  if(f&RowMajorBit) res += " | RowMajor";
686  if(f&PacketAccessBit) res += " | Packet";
687  if(f&LinearAccessBit) res += " | Linear";
688  if(f&LvalueBit) res += " | Lvalue";
689  if(f&DirectAccessBit) res += " | Direct";
690  if(f&NestByRefBit) res += " | NestByRef";
691  if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit";
692 
693  return res;
694 }
695 #endif
696 
697 } // end namespace internal
698 
699 // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
700 // that would take two operands of different types. If there were such an example, then this check should be
701 // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
702 // currently they take only one typename Scalar template parameter.
703 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
704 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
705 // add together a float matrix and a double matrix.
706 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
707  EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \
708  ? int(internal::scalar_product_traits<LHS, RHS>::Defined) \
709  : int(internal::is_same_or_void<LHS, RHS>::value)), \
710  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
711 
712 } // end namespace Eigen
713 
714 #endif // EIGEN_XPRHELPER_H
const unsigned int DirectAccessBit
Definition: Constants.h:149
const unsigned int LvalueBit
Definition: Constants.h:138
Definition: LDLT.h:16
const unsigned int RowMajorBit
Definition: Constants.h:61
const unsigned int PacketAccessBit
Definition: Constants.h:88
Definition: Constants.h:320
Definition: Constants.h:322
Definition: Eigen_Colamd.h:54
Definition: Constants.h:324
const unsigned int EvalBeforeNestingBit
Definition: Constants.h:65
const unsigned int LinearAccessBit
Definition: Constants.h:124
const unsigned int NoPreferredStorageOrderBit
Definition: Constants.h:172