XprHelper.h
Go to the documentation of this file.
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 
21 // useful for unsigned / signed integer comparisons when idx is intended to be non-negative
22 template <typename IndexType>
23 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename make_unsigned<IndexType>::type returnUnsignedIndexValue(
24  const IndexType& idx) {
25  EIGEN_STATIC_ASSERT((NumTraits<IndexType>::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES)
26  eigen_internal_assert(idx >= 0 && "Index value is negative and target type is unsigned");
27  using UnsignedType = typename make_unsigned<IndexType>::type;
28  return static_cast<UnsignedType>(idx);
29 }
30 
31 template <typename IndexDest, typename IndexSrc,
32  bool IndexDestIsInteger = NumTraits<IndexDest>::IsInteger,
33  bool IndexDestIsSigned = NumTraits<IndexDest>::IsSigned,
34  bool IndexSrcIsInteger = NumTraits<IndexSrc>::IsInteger,
35  bool IndexSrcIsSigned = NumTraits<IndexSrc>::IsSigned>
36 struct convert_index_impl {
37  static inline EIGEN_DEVICE_FUNC IndexDest run(const IndexSrc& idx) {
38  eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value is too big for target type");
39  return static_cast<IndexDest>(idx);
40  }
41 };
42 template <typename IndexDest, typename IndexSrc>
43 struct convert_index_impl<IndexDest, IndexSrc, true, true, true, false> {
44  // IndexDest is a signed integer
45  // IndexSrc is an unsigned integer
46  static inline EIGEN_DEVICE_FUNC IndexDest run(const IndexSrc& idx) {
47  eigen_internal_assert(idx <= returnUnsignedIndexValue(NumTraits<IndexDest>::highest()) &&
48  "Index value is too big for target type");
49  return static_cast<IndexDest>(idx);
50  }
51 };
52 template <typename IndexDest, typename IndexSrc>
53 struct convert_index_impl<IndexDest, IndexSrc, true, false, true, true> {
54  // IndexDest is an unsigned integer
55  // IndexSrc is a signed integer
56  static inline EIGEN_DEVICE_FUNC IndexDest run(const IndexSrc& idx) {
57  eigen_internal_assert(returnUnsignedIndexValue(idx) <= NumTraits<IndexDest>::highest() &&
58  "Index value is too big for target type");
59  return static_cast<IndexDest>(idx);
60  }
61 };
62 
63 template <typename IndexDest, typename IndexSrc>
64 EIGEN_DEVICE_FUNC inline IndexDest convert_index(const IndexSrc& idx) {
65  return convert_index_impl<IndexDest, IndexSrc>::run(idx);
66 }
67 
68 // true if T can be considered as an integral index (i.e., and integral type or enum)
69 template<typename T> struct is_valid_index_type
70 {
71  enum { value = internal::is_integral<T>::value || std::is_enum<T>::value
72  };
73 };
74 
75 // true if both types are not valid index types
76 template<typename RowIndices, typename ColIndices>
77 struct valid_indexed_view_overload {
78  enum { value = !(internal::is_valid_index_type<RowIndices>::value && internal::is_valid_index_type<ColIndices>::value) };
79 };
80 
81 // promote_scalar_arg is an helper used in operation between an expression and a scalar, like:
82 // expression * scalar
83 // 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.
84 // 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.
85 // Then the logic is as follows:
86 // - if the operation is natively supported as defined by IsSupported, then the scalar type is not promoted, and T is returned.
87 // - 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.
88 // - otherwise, ExprScalar is returned if T is implicitly convertible to ExprScalar AND that this does not imply a float to integer conversion.
89 // - In all other cases, the promoted type is not defined, and the respective operation is thus invalid and not available (SFINAE).
90 template<typename ExprScalar,typename T, bool IsSupported>
91 struct promote_scalar_arg;
92 
93 template<typename S,typename T>
94 struct promote_scalar_arg<S,T,true>
95 {
96  typedef T type;
97 };
98 
99 // Recursively check safe conversion to PromotedType, and then ExprScalar if they are different.
100 template<typename ExprScalar,typename T,typename PromotedType,
101  bool ConvertibleToLiteral = internal::is_convertible<T,PromotedType>::value,
103 struct promote_scalar_arg_unsupported;
104 
105 // Start recursion with NumTraits<ExprScalar>::Literal
106 template<typename S,typename T>
107 struct promote_scalar_arg<S,T,false> : promote_scalar_arg_unsupported<S,T,typename NumTraits<S>::Literal> {};
108 
109 // We found a match!
110 template<typename S,typename T, typename PromotedType>
111 struct promote_scalar_arg_unsupported<S,T,PromotedType,true,true>
112 {
113  typedef PromotedType type;
114 };
115 
116 // No match, but no real-to-integer issues, and ExprScalar and current PromotedType are different,
117 // so let's try to promote to ExprScalar
118 template<typename ExprScalar,typename T, typename PromotedType>
119 struct promote_scalar_arg_unsupported<ExprScalar,T,PromotedType,false,true>
120  : promote_scalar_arg_unsupported<ExprScalar,T,ExprScalar>
121 {};
122 
123 // Unsafe real-to-integer, let's stop.
124 template<typename S,typename T, typename PromotedType, bool ConvertibleToLiteral>
125 struct promote_scalar_arg_unsupported<S,T,PromotedType,ConvertibleToLiteral,false> {};
126 
127 // T is not even convertible to ExprScalar, let's stop.
128 template<typename S,typename T>
129 struct promote_scalar_arg_unsupported<S,T,S,false,true> {};
130 
131 //classes inheriting no_assignment_operator don't generate a default operator=.
132 class no_assignment_operator
133 {
134  private:
135  no_assignment_operator& operator=(const no_assignment_operator&);
136  protected:
137  EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator)
138  EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator)
139 };
140 
142 template<typename I1, typename I2>
143 struct promote_index_type
144 {
145  typedef std::conditional_t<(sizeof(I1)<sizeof(I2)), I2, I1> type;
146 };
147 
152 template<typename T, int Value> class variable_if_dynamic
153 {
154  public:
156  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
157  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
158  T value() { return T(Value); }
159  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
160  operator T() const { return T(Value); }
161  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
162  void setValue(T v) const { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
163 };
164 
165 template<typename T> class variable_if_dynamic<T, Dynamic>
166 {
167  T m_value;
168  public:
169  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value = 0) EIGEN_NO_THROW : m_value(value) {}
170  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; }
171  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator T() const { return m_value; }
172  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
173 };
174 
177 template<typename T, int Value> class variable_if_dynamicindex
178 {
179  public:
180  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
181  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
182  T value() { return T(Value); }
183  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
184  void setValue(T) {}
185 };
186 
187 template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
188 {
189  T m_value;
190  EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
191  public:
192  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamicindex(T value) : m_value(value) {}
193  EIGEN_DEVICE_FUNC T EIGEN_STRONG_INLINE value() const { return m_value; }
194  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
195 };
196 
197 template<typename T> struct functor_traits
198 {
199  enum
200  {
201  Cost = 10,
202  PacketAccess = false,
203  IsRepeatable = false
204  };
205 };
206 
207 template<typename T> struct packet_traits;
208 
209 template<typename T> struct unpacket_traits;
210 
211 template<int Size, typename PacketType,
212  bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
213 struct find_best_packet_helper;
214 
215 template< int Size, typename PacketType>
216 struct find_best_packet_helper<Size,PacketType,true>
217 {
218  typedef PacketType type;
219 };
220 
221 template<int Size, typename PacketType>
222 struct find_best_packet_helper<Size,PacketType,false>
223 {
224  typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
225 };
226 
227 template<typename T, int Size>
228 struct find_best_packet
229 {
230  typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
231 };
232 
233 template <int Size, typename PacketType,
234  bool Stop = (Size == unpacket_traits<PacketType>::size) ||
235  is_same<PacketType, typename unpacket_traits<PacketType>::half>::value>
236 struct find_packet_by_size_helper;
237 template <int Size, typename PacketType>
238 struct find_packet_by_size_helper<Size, PacketType, true> {
239  using type = PacketType;
240 };
241 template <int Size, typename PacketType>
242 struct find_packet_by_size_helper<Size, PacketType, false> {
243  using type = typename find_packet_by_size_helper<Size, typename unpacket_traits<PacketType>::half>::type;
244 };
245 
246 template <typename T, int Size>
247 struct find_packet_by_size {
248  using type = typename find_packet_by_size_helper<Size, typename packet_traits<T>::type>::type;
249  static constexpr bool value = (Size == unpacket_traits<type>::size);
250 };
251 template <typename T>
252 struct find_packet_by_size<T, 1> {
253  using type = typename unpacket_traits<T>::type;
254  static constexpr bool value = (unpacket_traits<type>::size == 1);
255 };
256 
257 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
258 constexpr inline int compute_default_alignment_helper(int ArrayBytes, int AlignmentBytes) {
259  if((ArrayBytes % AlignmentBytes) == 0) {
260  return AlignmentBytes;
261  } else if (EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) {
262  return compute_default_alignment_helper(ArrayBytes, AlignmentBytes/2);
263  } else {
264  return 0;
265  }
266 }
267 #else
268 // If static alignment is disabled, no need to bother.
269 // This also avoids a division by zero
270 constexpr inline int compute_default_alignment_helper(int ArrayBytes, int AlignmentBytes) {
271  EIGEN_UNUSED_VARIABLE(ArrayBytes);
272  EIGEN_UNUSED_VARIABLE(AlignmentBytes);
273  return 0;
274 }
275 #endif
276 
277 template<typename T, int Size> struct compute_default_alignment {
278  enum { value = compute_default_alignment_helper(Size*sizeof(T), EIGEN_MAX_STATIC_ALIGN_BYTES) };
279 };
280 
281 template<typename T> struct compute_default_alignment<T,Dynamic> {
282  enum { value = EIGEN_MAX_ALIGN_BYTES };
283 };
284 
285 template<typename Scalar_, int Rows_, int Cols_,
286  int Options_ = AutoAlign |
287  ( (Rows_==1 && Cols_!=1) ? RowMajor
288  : (Cols_==1 && Rows_!=1) ? ColMajor
290  int MaxRows_ = Rows_,
291  int MaxCols_ = Cols_
292 > class make_proper_matrix_type
293 {
294  enum {
295  IsColVector = Cols_==1 && Rows_!=1,
296  IsRowVector = Rows_==1 && Cols_!=1,
297  Options = IsColVector ? (Options_ | ColMajor) & ~RowMajor
298  : IsRowVector ? (Options_ | RowMajor) & ~ColMajor
299  : Options_
300  };
301  public:
302  typedef Matrix<Scalar_, Rows_, Cols_, Options, MaxRows_, MaxCols_> type;
303 };
304 
305 constexpr inline unsigned compute_matrix_flags(int Options) {
306  unsigned row_major_bit = Options&RowMajor ? RowMajorBit : 0;
307  // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
308  // and then propagate this information to the evaluator's flags.
309  // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
310  return DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit;
311 }
312 
313 constexpr inline int size_at_compile_time(int rows, int cols) {
314  if (rows == 0 || cols == 0) return 0;
315  if (rows == Dynamic || cols == Dynamic) return Dynamic;
316  return rows * cols;
317 }
318 
319 template<typename XprType> struct size_of_xpr_at_compile_time
320 {
321  enum { ret = size_at_compile_time(traits<XprType>::RowsAtCompileTime, traits<XprType>::ColsAtCompileTime) };
322 };
323 
324 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
325  * whereas eval is a const reference in the case of a matrix
326  */
327 
328 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
329 template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
330 template<typename T> struct plain_matrix_type<T,Dense>
331 {
332  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
333 };
334 template<typename T> struct plain_matrix_type<T,DiagonalShape>
335 {
336  typedef typename T::PlainObject type;
337 };
338 
339 template<typename T> struct plain_matrix_type<T,SkewSymmetricShape>
340 {
341  typedef typename T::PlainObject type;
342 };
343 
344 template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
345 {
347  traits<T>::RowsAtCompileTime,
348  traits<T>::ColsAtCompileTime,
349  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
350  traits<T>::MaxRowsAtCompileTime,
351  traits<T>::MaxColsAtCompileTime
352  > type;
353 };
354 
355 template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
356 {
358  traits<T>::RowsAtCompileTime,
359  traits<T>::ColsAtCompileTime,
360  AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
361  traits<T>::MaxRowsAtCompileTime,
362  traits<T>::MaxColsAtCompileTime
363  > type;
364 };
365 
366 /* eval : the return type of eval(). For matrices, this is just a const reference
367  * in order to avoid a useless copy
368  */
369 
370 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
371 
372 template<typename T> struct eval<T,Dense>
373 {
374  typedef typename plain_matrix_type<T>::type type;
375 // typedef typename T::PlainObject type;
376 // typedef T::Matrix<typename traits<T>::Scalar,
377 // traits<T>::RowsAtCompileTime,
378 // traits<T>::ColsAtCompileTime,
379 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
380 // traits<T>::MaxRowsAtCompileTime,
381 // traits<T>::MaxColsAtCompileTime
382 // > type;
383 };
384 
385 template<typename T> struct eval<T,DiagonalShape>
386 {
387  typedef typename plain_matrix_type<T>::type type;
388 };
389 
390 template<typename T> struct eval<T,SkewSymmetricShape>
391 {
392  typedef typename plain_matrix_type<T>::type type;
393 };
394 
395 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
396 template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
397 struct eval<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>, Dense>
398 {
399  typedef const Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>& type;
400 };
401 
402 template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
403 struct eval<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>, Dense>
404 {
405  typedef const Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>& type;
406 };
407 
408 
409 /* similar to plain_matrix_type, but using the evaluator's Flags */
410 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
411 
412 template<typename T>
413 struct plain_object_eval<T,Dense>
414 {
415  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
416 };
417 
418 
419 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
420  */
421 template<typename T> struct plain_matrix_type_column_major
422 {
423  enum { Rows = traits<T>::RowsAtCompileTime,
424  Cols = traits<T>::ColsAtCompileTime,
425  MaxRows = traits<T>::MaxRowsAtCompileTime,
426  MaxCols = traits<T>::MaxColsAtCompileTime
427  };
429  Rows,
430  Cols,
431  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
432  MaxRows,
433  MaxCols
434  > type;
435 };
436 
437 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
438  */
439 template<typename T> struct plain_matrix_type_row_major
440 {
441  enum { Rows = traits<T>::RowsAtCompileTime,
442  Cols = traits<T>::ColsAtCompileTime,
443  MaxRows = traits<T>::MaxRowsAtCompileTime,
444  MaxCols = traits<T>::MaxColsAtCompileTime
445  };
447  Rows,
448  Cols,
449  (MaxCols==1&&MaxRows!=1) ? ColMajor : RowMajor,
450  MaxRows,
451  MaxCols
452  > type;
453 };
454 
458 template <typename T>
459 struct ref_selector
460 {
461  typedef std::conditional_t<
462  bool(traits<T>::Flags & NestByRefBit),
463  T const&,
464  const T
465  > type;
466 
467  typedef std::conditional_t<
468  bool(traits<T>::Flags & NestByRefBit),
469  T &,
470  T
471  > non_const_type;
472 };
473 
475 template<typename T1, typename T2>
476 struct transfer_constness
477 {
478  typedef std::conditional_t<
479  bool(internal::is_const<T1>::value),
480  add_const_on_value_type_t<T2>,
481  T2
482  > type;
483 };
484 
485 
486 // However, we still need a mechanism to detect whether an expression which is evaluated multiple time
487 // has to be evaluated into a temporary.
488 // That's the purpose of this new nested_eval helper:
500 template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
501 {
502  enum {
503  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
504  CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a temporary?
505  // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
506  // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
507  // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
508  // Another solution could be to count the number of temps?
509  NAsInteger = n == Dynamic ? HugeCost : n,
510  CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
511  CostNoEval = NAsInteger * CoeffReadCost,
512  Evaluate = (int(evaluator<T>::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval))
513  };
514 
515  typedef std::conditional_t<Evaluate, PlainObject, typename ref_selector<T>::type> type;
516 };
517 
518 template<typename T>
520 inline T* const_cast_ptr(const T* ptr)
521 {
522  return const_cast<T*>(ptr);
523 }
524 
525 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
526 struct dense_xpr_base
527 {
528  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
529 };
530 
531 template<typename Derived>
532 struct dense_xpr_base<Derived, MatrixXpr>
533 {
534  typedef MatrixBase<Derived> type;
535 };
536 
537 template<typename Derived>
538 struct dense_xpr_base<Derived, ArrayXpr>
539 {
540  typedef ArrayBase<Derived> type;
541 };
542 
543 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
544 struct generic_xpr_base;
545 
546 template<typename Derived, typename XprKind>
547 struct generic_xpr_base<Derived, XprKind, Dense>
548 {
549  typedef typename dense_xpr_base<Derived,XprKind>::type type;
550 };
551 
552 template<typename XprType, typename CastType> struct cast_return_type
553 {
554  typedef typename XprType::Scalar CurrentScalarType;
555  typedef remove_all_t<CastType> CastType_;
556  typedef typename CastType_::Scalar NewScalarType;
557  typedef std::conditional_t<is_same<CurrentScalarType,NewScalarType>::value,
558  const XprType&,CastType> type;
559 };
560 
561 template <typename A, typename B> struct promote_storage_type;
562 
563 template <typename A> struct promote_storage_type<A,A>
564 {
565  typedef A ret;
566 };
567 template <typename A> struct promote_storage_type<A, const A>
568 {
569  typedef A ret;
570 };
571 template <typename A> struct promote_storage_type<const A, A>
572 {
573  typedef A ret;
574 };
575 
589 template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
590 
591 template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; };
592 template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; };
593 template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; };
594 template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; };
595 template <typename Functor> struct cwise_promote_storage_type<Sparse,Dense,Functor> { typedef Sparse ret; };
596 template <typename Functor> struct cwise_promote_storage_type<Dense,Sparse,Functor> { typedef Sparse ret; };
597 
598 template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order {
599  enum { value = LhsOrder };
600 };
601 
602 template <typename LhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder> { enum { value = RhsOrder }; };
603 template <typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder> { enum { value = LhsOrder }; };
604 template <int Order> struct cwise_promote_storage_order<Sparse,Sparse,Order,Order> { enum { value = Order }; };
605 
606 
621 template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
622 
623 template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;};
624 template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;};
625 template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; };
626 template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; };
627 
628 template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; };
629 template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; };
630 template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; };
631 template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; };
632 
633 template <typename A, int ProductTag> struct product_promote_storage_type<A, SkewSymmetricShape, ProductTag> { typedef A ret; };
634 template <typename B, int ProductTag> struct product_promote_storage_type<SkewSymmetricShape, B, ProductTag> { typedef B ret; };
635 template <int ProductTag> struct product_promote_storage_type<Dense, SkewSymmetricShape, ProductTag> { typedef Dense ret; };
636 template <int ProductTag> struct product_promote_storage_type<SkewSymmetricShape, Dense, ProductTag> { typedef Dense ret; };
637 template <int ProductTag> struct product_promote_storage_type<SkewSymmetricShape, SkewSymmetricShape, ProductTag> { typedef Dense ret; };
638 
639 template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; };
640 template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; };
641 template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; };
642 template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; };
643 
647 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
648 struct plain_row_type
649 {
650  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
651  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
652  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
653  int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
654 
655  typedef std::conditional_t<
656  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
657  MatrixRowType,
658  ArrayRowType
659  > type;
660 };
661 
662 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
663 struct plain_col_type
664 {
665  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
666  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
667  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
668  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
669 
670  typedef std::conditional_t<
671  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
672  MatrixColType,
673  ArrayColType
674  > type;
675 };
676 
677 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
678 struct plain_diag_type
679 {
680  enum { diag_size = internal::min_size_prefer_dynamic(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
681  max_diag_size = min_size_prefer_fixed(ExpressionType::MaxRowsAtCompileTime,
682  ExpressionType::MaxColsAtCompileTime)
683  };
684  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
685  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
686 
687  typedef std::conditional_t<
688  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
689  MatrixDiagType,
690  ArrayDiagType
691  > type;
692 };
693 
694 template<typename Expr,typename Scalar = typename Expr::Scalar>
695 struct plain_constant_type
696 {
697  enum { Options = (traits<Expr>::Flags&RowMajorBit)?RowMajor:0 };
698 
699  typedef Array<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
700  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> array_type;
701 
702  typedef Matrix<Scalar, traits<Expr>::RowsAtCompileTime, traits<Expr>::ColsAtCompileTime,
703  Options, traits<Expr>::MaxRowsAtCompileTime,traits<Expr>::MaxColsAtCompileTime> matrix_type;
704 
705  typedef CwiseNullaryOp<scalar_constant_op<Scalar>, const std::conditional_t<is_same< typename traits<Expr>::XprKind, MatrixXpr >::value, matrix_type, array_type> > type;
706 };
707 
708 template<typename ExpressionType>
709 struct is_lvalue
710 {
711  enum { value = (!bool(is_const<ExpressionType>::value)) &&
712  bool(traits<ExpressionType>::Flags & LvalueBit) };
713 };
714 
715 template<typename T> struct is_diagonal
716 { enum { ret = false }; };
717 
718 template<typename T> struct is_diagonal<DiagonalBase<T> >
719 { enum { ret = true }; };
720 
721 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
722 { enum { ret = true }; };
723 
724 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
725 { enum { ret = true }; };
726 
727 
728 template<typename T> struct is_identity
729 { enum { value = false }; };
730 
731 template<typename T> struct is_identity<CwiseNullaryOp<internal::scalar_identity_op<typename T::Scalar>, T> >
732 { enum { value = true }; };
733 
734 
735 template<typename S1, typename S2> struct glue_shapes;
736 template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; };
737 
738 template<typename T1, typename T2>
739 struct possibly_same_dense {
740  enum { value = has_direct_access<T1>::ret && has_direct_access<T2>::ret && is_same<typename T1::Scalar,typename T2::Scalar>::value };
741 };
742 
743 template<typename T1, typename T2>
745 bool is_same_dense(const T1 &mat1, const T2 &mat2, std::enable_if_t<possibly_same_dense<T1,T2>::value> * = 0)
746 {
747  return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
748 }
749 
750 template<typename T1, typename T2>
752 bool is_same_dense(const T1 &, const T2 &, std::enable_if_t<!possibly_same_dense<T1,T2>::value> * = 0)
753 {
754  return false;
755 }
756 
757 // Internal helper defining the cost of a scalar division for the type T.
758 // The default heuristic can be specialized for each scalar type and architecture.
759 template<typename T,bool Vectorized=false,typename EnableIf = void>
760 struct scalar_div_cost {
761  enum { value = 8*NumTraits<T>::MulCost };
762 };
763 
764 template<typename T,bool Vectorized>
765 struct scalar_div_cost<std::complex<T>, Vectorized> {
766  enum { value = 2*scalar_div_cost<T>::value
769  };
770 };
771 
772 
773 template<bool Vectorized>
774 struct scalar_div_cost<signed long,Vectorized, std::conditional_t<sizeof(long)==8,void,false_type>> { enum { value = 24 }; };
775 template<bool Vectorized>
776 struct scalar_div_cost<unsigned long,Vectorized, std::conditional_t<sizeof(long)==8,void,false_type>> { enum { value = 21 }; };
777 
778 
779 #ifdef EIGEN_DEBUG_ASSIGN
780 std::string demangle_traversal(int t)
781 {
782  if(t==DefaultTraversal) return "DefaultTraversal";
783  if(t==LinearTraversal) return "LinearTraversal";
784  if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
785  if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
786  if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
787  return "?";
788 }
789 std::string demangle_unrolling(int t)
790 {
791  if(t==NoUnrolling) return "NoUnrolling";
792  if(t==InnerUnrolling) return "InnerUnrolling";
793  if(t==CompleteUnrolling) return "CompleteUnrolling";
794  return "?";
795 }
796 std::string demangle_flags(int f)
797 {
798  std::string res;
799  if(f&RowMajorBit) res += " | RowMajor";
800  if(f&PacketAccessBit) res += " | Packet";
801  if(f&LinearAccessBit) res += " | Linear";
802  if(f&LvalueBit) res += " | Lvalue";
803  if(f&DirectAccessBit) res += " | Direct";
804  if(f&NestByRefBit) res += " | NestByRef";
805  if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit";
806 
807  return res;
808 }
809 #endif
810 
811 } // end namespace internal
812 
813 
850 template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
852 #ifndef EIGEN_PARSED_BY_DOXYGEN
853  // for backward compatibility, use the hints given by the (deprecated) internal::scalar_product_traits class.
854  : internal::scalar_product_traits<ScalarA,ScalarB>
855 #endif // EIGEN_PARSED_BY_DOXYGEN
856 {};
857 
858 template<typename T, typename BinaryOp>
860 {
861  typedef T ReturnType;
862 };
863 
864 template <typename T, typename BinaryOp>
865 struct ScalarBinaryOpTraits<T, typename NumTraits<std::enable_if_t<NumTraits<T>::IsComplex,T>>::Real, BinaryOp>
866 {
867  typedef T ReturnType;
868 };
869 template <typename T, typename BinaryOp>
870 struct ScalarBinaryOpTraits<typename NumTraits<std::enable_if_t<NumTraits<T>::IsComplex,T>>::Real, T, BinaryOp>
871 {
872  typedef T ReturnType;
873 };
874 
875 // For Matrix * Permutation
876 template<typename T, typename BinaryOp>
878 {
879  typedef T ReturnType;
880 };
881 
882 // For Permutation * Matrix
883 template<typename T, typename BinaryOp>
885 {
886  typedef T ReturnType;
887 };
888 
889 // for Permutation*Permutation
890 template<typename BinaryOp>
892 {
893  typedef void ReturnType;
894 };
895 
896 // We require Lhs and Rhs to have "compatible" scalar types.
897 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
898 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
899 // add together a float matrix and a double matrix.
900 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
901  EIGEN_STATIC_ASSERT((Eigen::internal::has_ReturnType<ScalarBinaryOpTraits<LHS, RHS,BINOP> >::value), \
902  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
903 
904 } // end namespace Eigen
905 
906 #endif // EIGEN_XPRHELPER_H
Array< int, Dynamic, 1 > v
int n
MatrixXcf A
#define EIGEN_MIN_ALIGN_BYTES
#define EIGEN_MAX_STATIC_ALIGN_BYTES
#define EIGEN_MAX_ALIGN_BYTES
MatrixXf B
#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS)
Definition: Macros.h:1113
#define eigen_internal_assert(x)
Definition: Macros.h:908
#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived)
Definition: Macros.h:1133
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define EIGEN_UNUSED_VARIABLE(var)
Definition: Macros.h:957
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
Definition: Macros.h:914
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
Definition: Macros.h:30
#define eigen_assert(x)
Definition: Macros.h:902
#define EIGEN_NO_THROW
Definition: Macros.h:1262
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
MatrixXd mat1(size, size)
Eigen::Triplet< double > T
internal::traits< Matrix< Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_ > >::Scalar Scalar
@ 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
constexpr unsigned compute_matrix_flags(int Options)
Definition: XprHelper.h:305
constexpr int size_at_compile_time(int rows, int cols)
Definition: XprHelper.h:313
make_unsigned< IndexType >::type returnUnsignedIndexValue(const IndexType &idx)
Definition: XprHelper.h:23
constexpr int min_size_prefer_fixed(A a, B b)
Definition: Meta.h:553
T * const_cast_ptr(const T *ptr)
Definition: XprHelper.h:520
IndexDest convert_index(const IndexSrc &idx)
Definition: XprHelper.h:64
bool is_same_dense(const T1 &mat1, const T2 &mat2, std::enable_if_t< possibly_same_dense< T1, T2 >::value > *=0)
Definition: XprHelper.h:745
constexpr int min_size_prefer_dynamic(A a, B b)
Definition: Meta.h:537
constexpr int compute_default_alignment_helper(int ArrayBytes, int AlignmentBytes)
Definition: XprHelper.h:270
: InteropHeaders
Definition: Core:139
const unsigned int NestByRefBit
Definition: Constants.h:171
const int HugeCost
Definition: Constants.h:46
@ InnerVectorizedTraversal
Definition: Constants.h:284
@ LinearVectorizedTraversal
Definition: Constants.h:287
@ DefaultTraversal
Definition: Constants.h:279
@ SliceVectorizedTraversal
Definition: Constants.h:290
@ LinearTraversal
Definition: Constants.h:281
const int DynamicIndex
Definition: Constants.h:29
@ InnerUnrolling
Definition: Constants.h:303
@ CompleteUnrolling
Definition: Constants.h:306
@ NoUnrolling
Definition: Constants.h:301
const int Dynamic
Definition: Constants.h:24
Definition: BFloat16.h:222
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:231
Determines whether the given binary operation of two numeric types is allowed and what the scalar ret...
Definition: XprHelper.h:856