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