Eigen  3.4.90 (git rev 67eeba6e720c5745abc77ae6c92ce0a44aa7b7ae)
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 #include "../InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 template<typename IndexDest, typename IndexSrc>
21 EIGEN_DEVICE_FUNC
22 inline IndexDest convert_index(const IndexSrc& idx) {
23  // for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away:
24  eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value to big for target type");
25  return IndexDest(idx);
26 }
27 
28 // true if T can be considered as an integral index (i.e., and integral type or enum)
29 template<typename T> struct is_valid_index_type
30 {
31  enum { value = internal::is_integral<T>::value || std::is_enum<T>::value
32  };
33 };
34 
35 // true if both types are not valid index types
36 template<typename RowIndices, typename ColIndices>
37 struct valid_indexed_view_overload {
38  enum { value = !(internal::is_valid_index_type<RowIndices>::value && internal::is_valid_index_type<ColIndices>::value) };
39 };
40 
41 // promote_scalar_arg is an helper used in operation between an expression and a scalar, like:
42 // expression * scalar
43 // 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.
44 // 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.
45 // Then the logic is as follows:
46 // - if the operation is natively supported as defined by IsSupported, then the scalar type is not promoted, and T is returned.
47 // - 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.
48 // - otherwise, ExprScalar is returned if T is implicitly convertible to ExprScalar AND that this does not imply a float to integer conversion.
49 // - In all other cases, the promoted type is not defined, and the respective operation is thus invalid and not available (SFINAE).
50 template<typename ExprScalar,typename T, bool IsSupported>
51 struct promote_scalar_arg;
52 
53 template<typename S,typename T>
54 struct promote_scalar_arg<S,T,true>
55 {
56  typedef T type;
57 };
58 
59 // Recursively check safe conversion to PromotedType, and then ExprScalar if they are different.
60 template<typename ExprScalar,typename T,typename PromotedType,
61  bool ConvertibleToLiteral = internal::is_convertible<T,PromotedType>::value,
62  bool IsSafe = NumTraits<T>::IsInteger || !NumTraits<PromotedType>::IsInteger>
63 struct promote_scalar_arg_unsupported;
64 
65 // Start recursion with NumTraits<ExprScalar>::Literal
66 template<typename S,typename T>
67 struct promote_scalar_arg<S,T,false> : promote_scalar_arg_unsupported<S,T,typename NumTraits<S>::Literal> {};
68 
69 // We found a match!
70 template<typename S,typename T, typename PromotedType>
71 struct promote_scalar_arg_unsupported<S,T,PromotedType,true,true>
72 {
73  typedef PromotedType type;
74 };
75 
76 // No match, but no real-to-integer issues, and ExprScalar and current PromotedType are different,
77 // so let's try to promote to ExprScalar
78 template<typename ExprScalar,typename T, typename PromotedType>
79 struct promote_scalar_arg_unsupported<ExprScalar,T,PromotedType,false,true>
80  : promote_scalar_arg_unsupported<ExprScalar,T,ExprScalar>
81 {};
82 
83 // Unsafe real-to-integer, let's stop.
84 template<typename S,typename T, typename PromotedType, bool ConvertibleToLiteral>
85 struct promote_scalar_arg_unsupported<S,T,PromotedType,ConvertibleToLiteral,false> {};
86 
87 // T is not even convertible to ExprScalar, let's stop.
88 template<typename S,typename T>
89 struct promote_scalar_arg_unsupported<S,T,S,false,true> {};
90 
91 //classes inheriting no_assignment_operator don't generate a default operator=.
92 class no_assignment_operator
93 {
94  private:
95  no_assignment_operator& operator=(const no_assignment_operator&);
96  protected:
97  EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator)
98  EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator)
99 };
100 
102 template<typename I1, typename I2>
103 struct promote_index_type
104 {
105  typedef std::conditional_t<(sizeof(I1)<sizeof(I2)), I2, I1> type;
106 };
107 
112 template<typename T, int Value> class variable_if_dynamic
113 {
114  public:
115  EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(variable_if_dynamic)
116  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
117  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
118  T value() { return T(Value); }
119  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
120  operator T() const { return T(Value); }
121  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
122  void setValue(T v) const { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
123 };
124 
125 template<typename T> class variable_if_dynamic<T, Dynamic>
126 {
127  T m_value;
128  public:
129  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value = 0) EIGEN_NO_THROW : m_value(value) {}
130  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; }
131  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator T() const { return m_value; }
132  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
133 };
134 
137 template<typename T, int Value> class variable_if_dynamicindex
138 {
139  public:
140  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
141  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
142  T value() { return T(Value); }
143  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
144  void setValue(T) {}
145 };
146 
147 template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
148 {
149  T m_value;
150  EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
151  public:
152  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T value) : m_value(value) {}
153  EIGEN_DEVICE_FUNC T EIGEN_STRONG_INLINE value() const { return m_value; }
154  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
155 };
156 
157 template<typename T> struct functor_traits
158 {
159  enum
160  {
161  Cost = 10,
162  PacketAccess = false,
163  IsRepeatable = false
164  };
165 };
166 
167 template<typename T> struct packet_traits;
168 
169 template<typename T> struct unpacket_traits;
170 
171 template<int Size, typename PacketType,
172  bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
173 struct find_best_packet_helper;
174 
175 template< int Size, typename PacketType>
176 struct find_best_packet_helper<Size,PacketType,true>
177 {
178  typedef PacketType type;
179 };
180 
181 template<int Size, typename PacketType>
182 struct find_best_packet_helper<Size,PacketType,false>
183 {
184  typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
185 };
186 
187 template<typename T, int Size>
188 struct find_best_packet
189 {
190  typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
191 };
192 
193 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
194 constexpr inline int compute_default_alignment_helper(int ArrayBytes, int AlignmentBytes) {
195  if((ArrayBytes % AlignmentBytes) == 0) {
196  return AlignmentBytes;
197  } else if (EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) {
198  return compute_default_alignment_helper(ArrayBytes, AlignmentBytes/2);
199  } else {
200  return 0;
201  }
202 }
203 #else
204 // If static alignment is disabled, no need to bother.
205 // This also avoids a division by zero
206 constexpr inline int compute_default_alignment_helper(int ArrayBytes, int AlignmentBytes) {
207  EIGEN_UNUSED_VARIABLE(ArrayBytes);
208  EIGEN_UNUSED_VARIABLE(AlignmentBytes);
209  return 0;
210 }
211 #endif
212 
213 template<typename T, int Size> struct compute_default_alignment {
214  enum { value = compute_default_alignment_helper(Size*sizeof(T), EIGEN_MAX_STATIC_ALIGN_BYTES) };
215 };
216 
217 template<typename T> struct compute_default_alignment<T,Dynamic> {
218  enum { value = EIGEN_MAX_ALIGN_BYTES };
219 };
220 
221 template<typename Scalar_, int Rows_, int Cols_,
222  int Options_ = AutoAlign |
223  ( (Rows_==1 && Cols_!=1) ? RowMajor
224  : (Cols_==1 && Rows_!=1) ? ColMajor
225  : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
226  int MaxRows_ = Rows_,
227  int MaxCols_ = Cols_
228 > class make_proper_matrix_type
229 {
230  enum {
231  IsColVector = Cols_==1 && Rows_!=1,
232  IsRowVector = Rows_==1 && Cols_!=1,
233  Options = IsColVector ? (Options_ | ColMajor) & ~RowMajor
234  : IsRowVector ? (Options_ | RowMajor) & ~ColMajor
235  : Options_
236  };
237  public:
238  typedef Matrix<Scalar_, Rows_, Cols_, Options, MaxRows_, MaxCols_> type;
239 };
240 
241 constexpr inline unsigned compute_matrix_flags(int Options) {
242  unsigned row_major_bit = Options&RowMajor ? RowMajorBit : 0;
243  // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
244  // and then propagate this information to the evaluator's flags.
245  // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
246  return DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit;
247 }
248 
249 constexpr inline int size_at_compile_time(int rows, int cols) {
250  return (rows==Dynamic || cols==Dynamic) ? Dynamic : rows * cols;
251 }
252 
253 template<typename XprType> struct size_of_xpr_at_compile_time
254 {
255  enum { ret = size_at_compile_time(traits<XprType>::RowsAtCompileTime, traits<XprType>::ColsAtCompileTime) };
256 };
257 
258 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
259  * whereas eval is a const reference in the case of a matrix
260  */
261 
262 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
263 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
264 template<typename T> struct plain_matrix_type<T,Dense>
265 {
266  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
267 };
268 template<typename T> struct plain_matrix_type<T,DiagonalShape>
269 {
270  typedef typename T::PlainObject type;
271 };
272 
273 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
274 {
275  typedef Matrix<typename traits<T>::Scalar,
276  traits<T>::RowsAtCompileTime,
277  traits<T>::ColsAtCompileTime,
278  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
279  traits<T>::MaxRowsAtCompileTime,
280  traits<T>::MaxColsAtCompileTime
281  > type;
282 };
283 
284 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
285 {
286  typedef Array<typename traits<T>::Scalar,
287  traits<T>::RowsAtCompileTime,
288  traits<T>::ColsAtCompileTime,
289  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
290  traits<T>::MaxRowsAtCompileTime,
291  traits<T>::MaxColsAtCompileTime
292  > type;
293 };
294 
295 /* eval : the return type of eval(). For matrices, this is just a const reference
296  * in order to avoid a useless copy
297  */
298 
299 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
300 
301 template<typename T> struct eval<T,Dense>
302 {
303  typedef typename plain_matrix_type<T>::type type;
304 // typedef typename T::PlainObject type;
305 // typedef T::Matrix<typename traits<T>::Scalar,
306 // traits<T>::RowsAtCompileTime,
307 // traits<T>::ColsAtCompileTime,
308 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
309 // traits<T>::MaxRowsAtCompileTime,
310 // traits<T>::MaxColsAtCompileTime
311 // > type;
312 };
313 
314 template<typename T> struct eval<T,DiagonalShape>
315 {
316  typedef typename plain_matrix_type<T>::type type;
317 };
318 
319 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
320 template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
321 struct eval<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>, Dense>
322 {
323  typedef const Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>& type;
324 };
325 
326 template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
327 struct eval<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>, Dense>
328 {
329  typedef const Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>& type;
330 };
331 
332 
333 /* similar to plain_matrix_type, but using the evaluator's Flags */
334 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
335 
336 template<typename T>
337 struct plain_object_eval<T,Dense>
338 {
339  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
340 };
341 
342 
343 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
344  */
345 template<typename T> struct plain_matrix_type_column_major
346 {
347  enum { Rows = traits<T>::RowsAtCompileTime,
348  Cols = traits<T>::ColsAtCompileTime,
349  MaxRows = traits<T>::MaxRowsAtCompileTime,
350  MaxCols = traits<T>::MaxColsAtCompileTime
351  };
352  typedef Matrix<typename traits<T>::Scalar,
353  Rows,
354  Cols,
355  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
356  MaxRows,
357  MaxCols
358  > type;
359 };
360 
361 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
362  */
363 template<typename T> struct plain_matrix_type_row_major
364 {
365  enum { Rows = traits<T>::RowsAtCompileTime,
366  Cols = traits<T>::ColsAtCompileTime,
367  MaxRows = traits<T>::MaxRowsAtCompileTime,
368  MaxCols = traits<T>::MaxColsAtCompileTime
369  };
370  typedef Matrix<typename traits<T>::Scalar,
371  Rows,
372  Cols,
373  (MaxCols==1&&MaxRows!=1) ? ColMajor : RowMajor,
374  MaxRows,
375  MaxCols
376  > type;
377 };
378 
382 template <typename T>
383 struct ref_selector
384 {
385  typedef std::conditional_t<
386  bool(traits<T>::Flags & NestByRefBit),
387  T const&,
388  const T
389  > type;
390 
391  typedef std::conditional_t<
392  bool(traits<T>::Flags & NestByRefBit),
393  T &,
394  T
395  > non_const_type;
396 };
397 
399 template<typename T1, typename T2>
400 struct transfer_constness
401 {
402  typedef std::conditional_t<
403  bool(internal::is_const<T1>::value),
404  add_const_on_value_type_t<T2>,
405  T2
406  > type;
407 };
408 
409 
410 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time
411 // has to be evaluated into a temporary.
412 // That's the purpose of this new nested_eval helper:
424 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
425 {
426  enum {
427  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
428  CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a temporary?
429  // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
430  // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
431  // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
432  // Another solution could be to count the number of temps?
433  NAsInteger = n == Dynamic ? HugeCost : n,
434  CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
435  CostNoEval = NAsInteger * CoeffReadCost,
436  Evaluate = (int(evaluator<T>::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval))
437  };
438 
439  typedef std::conditional_t<Evaluate, PlainObject, typename ref_selector<T>::type> type;
440 };
441 
442 template<typename T>
443 EIGEN_DEVICE_FUNC
444 inline T* const_cast_ptr(const T* ptr)
445 {
446  return const_cast<T*>(ptr);
447 }
448 
449 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
450 struct dense_xpr_base
451 {
452  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
453 };
454 
455 template<typename Derived>
456 struct dense_xpr_base<Derived, MatrixXpr>
457 {
458  typedef MatrixBase<Derived> type;
459 };
460 
461 template<typename Derived>
462 struct dense_xpr_base<Derived, ArrayXpr>
463 {
464  typedef ArrayBase<Derived> type;
465 };
466 
467 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
468 struct generic_xpr_base;
469 
470 template<typename Derived, typename XprKind>
471 struct generic_xpr_base<Derived, XprKind, Dense>
472 {
473  typedef typename dense_xpr_base<Derived,XprKind>::type type;
474 };
475 
476 template<typename XprType, typename CastType> struct cast_return_type
477 {
478  typedef typename XprType::Scalar CurrentScalarType;
479  typedef remove_all_t<CastType> CastType_;
480  typedef typename CastType_::Scalar NewScalarType;
481  typedef std::conditional_t<is_same<CurrentScalarType,NewScalarType>::value,
482  const XprType&,CastType> type;
483 };
484 
485 template <typename A, typename B> struct promote_storage_type;
486 
487 template <typename A> struct promote_storage_type<A,A>
488 {
489  typedef A ret;
490 };
491 template <typename A> struct promote_storage_type<A, const A>
492 {
493  typedef A ret;
494 };
495 template <typename A> struct promote_storage_type<const A, A>
496 {
497  typedef A ret;
498 };
499 
513 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
514 
515 template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; };
516 template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; };
517 template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; };
518 template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; };
519 template <typename Functor> struct cwise_promote_storage_type<Sparse,Dense,Functor> { typedef Sparse ret; };
520 template <typename Functor> struct cwise_promote_storage_type<Dense,Sparse,Functor> { typedef Sparse ret; };
521 
522 template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order {
523  enum { value = LhsOrder };
524 };
525 
526 template <typename LhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder> { enum { value = RhsOrder }; };
527 template <typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder> { enum { value = LhsOrder }; };
528 template <int Order> struct cwise_promote_storage_order<Sparse,Sparse,Order,Order> { enum { value = Order }; };
529 
530 
545 template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
546 
547 template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;};
548 template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;};
549 template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; };
550 template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; };
551 
552 template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; };
553 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; };
554 template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; };
555 template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; };
556 
557 template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; };
558 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; };
559 template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; };
560 template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; };
561 
565 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
566 struct plain_row_type
567 {
568  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
569  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
570  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
571  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
572 
573  typedef std::conditional_t<
574  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
575  MatrixRowType,
576  ArrayRowType
577  > type;
578 };
579 
580 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
581 struct plain_col_type
582 {
583  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
584  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
585  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
586  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
587 
588  typedef std::conditional_t<
589  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
590  MatrixColType,
591  ArrayColType
592  > type;
593 };
594 
595 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
596 struct plain_diag_type
597 {
598  enum { diag_size = internal::min_size_prefer_dynamic(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
599  max_diag_size = min_size_prefer_fixed(ExpressionType::MaxRowsAtCompileTime,
600  ExpressionType::MaxColsAtCompileTime)
601  };
602  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
603  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
604 
605  typedef std::conditional_t<
606  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
607  MatrixDiagType,
608  ArrayDiagType
609  > type;
610 };
611 
612 template<typename Expr,typename Scalar = typename Expr::Scalar>
613 struct plain_constant_type
614 {
615  enum { Options = (traits<Expr>::Flags&RowMajorBit)?RowMajor:0 };
616 
617  typedef Array<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
618  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> array_type;
619 
620  typedef Matrix<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
621  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> matrix_type;
622 
623  typedef CwiseNullaryOp<scalar_constant_op<Scalar>, const std::conditional_t<is_same< typename traits<Expr>::XprKind, MatrixXpr >::value, matrix_type, array_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 
646 template<typename T> struct is_identity
647 { enum { value = false }; };
648 
649 template<typename T> struct is_identity<CwiseNullaryOp<internal::scalar_identity_op<typename T::Scalar>, T> >
650 { enum { value = true }; };
651 
652 
653 template<typename S1, typename S2> struct glue_shapes;
654 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; };
655 
656 template<typename T1, typename T2>
657 struct possibly_same_dense {
658  enum { value = has_direct_access<T1>::ret && has_direct_access<T2>::ret && is_same<typename T1::Scalar,typename T2::Scalar>::value };
659 };
660 
661 template<typename T1, typename T2>
662 EIGEN_DEVICE_FUNC
663 bool is_same_dense(const T1 &mat1, const T2 &mat2, std::enable_if_t<possibly_same_dense<T1,T2>::value> * = 0)
664 {
665  return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
666 }
667 
668 template<typename T1, typename T2>
669 EIGEN_DEVICE_FUNC
670 bool is_same_dense(const T1 &, const T2 &, std::enable_if_t<!possibly_same_dense<T1,T2>::value> * = 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 EnableIf = 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, std::conditional_t<sizeof(long)==8,void,false_type>> { enum { value = 24 }; };
693 template<bool Vectorized>
694 struct scalar_div_cost<unsigned long,Vectorized, std::conditional_t<sizeof(long)==8,void,false_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<std::enable_if_t<NumTraits<T>::IsComplex,T>>::Real, BinaryOp>
784 {
785  typedef T ReturnType;
786 };
787 template <typename T, typename BinaryOp>
788 struct ScalarBinaryOpTraits<typename NumTraits<std::enable_if_t<NumTraits<T>::IsComplex,T>>::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
@ RowsAtCompileTime
Definition: DenseBase.h:95
@ ColMajor
Definition: Constants.h:321
@ RowMajor
Definition: Constants.h:323
@ AutoAlign
Definition: Constants.h:325
const unsigned int PacketAccessBit
Definition: Constants.h:96
const unsigned int NoPreferredStorageOrderBit
Definition: Constants.h:180
const unsigned int LinearAccessBit
Definition: Constants.h:132
const unsigned int EvalBeforeNestingBit
Definition: Constants.h:72
const unsigned int DirectAccessBit
Definition: Constants.h:157
const unsigned int LvalueBit
Definition: Constants.h:146
const unsigned int RowMajorBit
Definition: Constants.h:68
Namespace containing all symbols from the Eigen library.
Definition: Core:139
const int HugeCost
Definition: Constants.h:46
const int DynamicIndex
Definition: Constants.h:29
const int Dynamic
Definition: Constants.h:24
Determines whether the given binary operation of two numeric types is allowed and what the scalar ret...
Definition: XprHelper.h:774