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