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 (defined __GNUG__) && !((__GNUC__==4) && (__GNUC_MINOR__==3))
18  #define EIGEN_EMPTY_STRUCT_CTOR(X) \
19  EIGEN_STRONG_INLINE X() {} \
20  EIGEN_STRONG_INLINE X(const X& ) {}
21 #else
22  #define EIGEN_EMPTY_STRUCT_CTOR(X)
23 #endif
24 
25 namespace Eigen {
26 
27 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
28 
29 namespace internal {
30 
31 //classes inheriting no_assignment_operator don't generate a default operator=.
32 class no_assignment_operator
33 {
34  private:
35  no_assignment_operator& operator=(const no_assignment_operator&);
36 };
37 
39 template<typename I1, typename I2>
40 struct promote_index_type
41 {
42  typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
43 };
44 
49 template<typename T, int Value> class variable_if_dynamic
50 {
51  public:
52  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
53  explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); }
54  static T value() { return T(Value); }
55  void setValue(T) {}
56 };
57 
58 template<typename T> class variable_if_dynamic<T, Dynamic>
59 {
60  T m_value;
61  variable_if_dynamic() { assert(false); }
62  public:
63  explicit variable_if_dynamic(T value) : m_value(value) {}
64  T value() const { return m_value; }
65  void setValue(T value) { m_value = value; }
66 };
67 
68 template<typename T> struct functor_traits
69 {
70  enum
71  {
72  Cost = 10,
73  PacketAccess = false
74  };
75 };
76 
77 template<typename T> struct packet_traits;
78 
79 template<typename T> struct unpacket_traits
80 {
81  typedef T type;
82  enum {size=1};
83 };
84 
85 template<typename _Scalar, int _Rows, int _Cols,
86  int _Options = AutoAlign |
87  ( (_Rows==1 && _Cols!=1) ? RowMajor
88  : (_Cols==1 && _Rows!=1) ? ColMajor
89  : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
90  int _MaxRows = _Rows,
91  int _MaxCols = _Cols
92 > class make_proper_matrix_type
93 {
94  enum {
95  IsColVector = _Cols==1 && _Rows!=1,
96  IsRowVector = _Rows==1 && _Cols!=1,
97  Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
98  : IsRowVector ? (_Options | RowMajor) & ~ColMajor
99  : _Options
100  };
101  public:
102  typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
103 };
104 
105 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
106 class compute_matrix_flags
107 {
108  enum {
109  row_major_bit = Options&RowMajor ? RowMajorBit : 0,
110  is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic,
111 
112  aligned_bit =
113  (
114  ((Options&DontAlign)==0)
115  && (
116 #if EIGEN_ALIGN_STATICALLY
117  ((!is_dynamic_size_storage) && (((MaxCols*MaxRows*int(sizeof(Scalar))) % 16) == 0))
118 #else
119  0
120 #endif
121 
122  ||
123 
124 #if EIGEN_ALIGN
125  is_dynamic_size_storage
126 #else
127  0
128 #endif
129 
130  )
131  ) ? AlignedBit : 0,
132  packet_access_bit = packet_traits<Scalar>::Vectorizable && aligned_bit ? PacketAccessBit : 0
133  };
134 
135  public:
136  enum { ret = LinearAccessBit | LvalueBit | DirectAccessBit | NestByRefBit | packet_access_bit | row_major_bit | aligned_bit };
137 };
138 
139 template<int _Rows, int _Cols> struct size_at_compile_time
140 {
141  enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
142 };
143 
144 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
145  * whereas eval is a const reference in the case of a matrix
146  */
147 
148 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
149 template<typename T, typename BaseClassType> struct plain_matrix_type_dense;
150 template<typename T> struct plain_matrix_type<T,Dense>
151 {
152  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind>::type type;
153 };
154 
155 template<typename T> struct plain_matrix_type_dense<T,MatrixXpr>
156 {
157  typedef Matrix<typename traits<T>::Scalar,
158  traits<T>::RowsAtCompileTime,
159  traits<T>::ColsAtCompileTime,
160  AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
161  traits<T>::MaxRowsAtCompileTime,
162  traits<T>::MaxColsAtCompileTime
163  > type;
164 };
165 
166 template<typename T> struct plain_matrix_type_dense<T,ArrayXpr>
167 {
168  typedef Array<typename traits<T>::Scalar,
169  traits<T>::RowsAtCompileTime,
170  traits<T>::ColsAtCompileTime,
171  AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
172  traits<T>::MaxRowsAtCompileTime,
173  traits<T>::MaxColsAtCompileTime
174  > type;
175 };
176 
177 /* eval : the return type of eval(). For matrices, this is just a const reference
178  * in order to avoid a useless copy
179  */
180 
181 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
182 
183 template<typename T> struct eval<T,Dense>
184 {
185  typedef typename plain_matrix_type<T>::type type;
186 // typedef typename T::PlainObject type;
187 // typedef T::Matrix<typename traits<T>::Scalar,
188 // traits<T>::RowsAtCompileTime,
189 // traits<T>::ColsAtCompileTime,
190 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
191 // traits<T>::MaxRowsAtCompileTime,
192 // traits<T>::MaxColsAtCompileTime
193 // > type;
194 };
195 
196 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
197 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
198 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
199 {
200  typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
201 };
202 
203 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
204 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
205 {
206  typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
207 };
208 
209 
210 
211 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
212  */
213 template<typename T> struct plain_matrix_type_column_major
214 {
215  enum { Rows = traits<T>::RowsAtCompileTime,
216  Cols = traits<T>::ColsAtCompileTime,
217  MaxRows = traits<T>::MaxRowsAtCompileTime,
218  MaxCols = traits<T>::MaxColsAtCompileTime
219  };
220  typedef Matrix<typename traits<T>::Scalar,
221  Rows,
222  Cols,
223  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
224  MaxRows,
225  MaxCols
226  > type;
227 };
228 
229 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
230  */
231 template<typename T> struct plain_matrix_type_row_major
232 {
233  enum { Rows = traits<T>::RowsAtCompileTime,
234  Cols = traits<T>::ColsAtCompileTime,
235  MaxRows = traits<T>::MaxRowsAtCompileTime,
236  MaxCols = traits<T>::MaxColsAtCompileTime
237  };
238  typedef Matrix<typename traits<T>::Scalar,
239  Rows,
240  Cols,
241  (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
242  MaxRows,
243  MaxCols
244  > type;
245 };
246 
247 // we should be able to get rid of this one too
248 template<typename T> struct must_nest_by_value { enum { ret = false }; };
249 
253 template <typename T>
254 struct ref_selector
255 {
256  typedef typename conditional<
257  bool(traits<T>::Flags & NestByRefBit),
258  T const&,
259  const T
260  >::type type;
261 };
262 
264 template<typename T1, typename T2>
265 struct transfer_constness
266 {
267  typedef typename conditional<
268  bool(internal::is_const<T1>::value),
269  typename internal::add_const_on_value_type<T2>::type,
270  T2
271  >::type type;
272 };
273 
294 template<typename T, int n=1, typename PlainObject = typename eval<T>::type> struct nested
295 {
296  enum {
297  // for the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values.
298  // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values.
299  // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues
300  // (poor choice of temporaries).
301  // it's important that this value can still be squared without integer overflowing.
302  DynamicAsInteger = 10000,
303  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
304  ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost),
305  CoeffReadCost = traits<T>::CoeffReadCost,
306  CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost),
307  NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n,
308  CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger,
309  CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger
310  };
311 
312  typedef typename conditional<
313  ( (int(traits<T>::Flags) & EvalBeforeNestingBit) ||
314  int(CostEvalAsInteger) < int(CostNoEvalAsInteger)
315  ),
316  PlainObject,
317  typename ref_selector<T>::type
318  >::type type;
319 };
320 
321 template<typename T>
322 T* const_cast_ptr(const T* ptr)
323 {
324  return const_cast<T*>(ptr);
325 }
326 
327 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
328 struct dense_xpr_base
329 {
330  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
331 };
332 
333 template<typename Derived>
334 struct dense_xpr_base<Derived, MatrixXpr>
335 {
336  typedef MatrixBase<Derived> type;
337 };
338 
339 template<typename Derived>
340 struct dense_xpr_base<Derived, ArrayXpr>
341 {
342  typedef ArrayBase<Derived> type;
343 };
344 
347 template<typename Derived,typename Scalar,typename OtherScalar,
348  bool EnableIt = !is_same<Scalar,OtherScalar>::value >
349 struct special_scalar_op_base : public DenseCoeffsBase<Derived>
350 {
351  // dummy operator* so that the
352  // "using special_scalar_op_base::operator*" compiles
353  void operator*() const;
354 };
355 
356 template<typename Derived,typename Scalar,typename OtherScalar>
357 struct special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCoeffsBase<Derived>
358 {
359  const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
360  operator*(const OtherScalar& scalar) const
361  {
362  return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
363  (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar));
364  }
365 
366  inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
367  operator*(const OtherScalar& scalar, const Derived& matrix)
368  { return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); }
369 };
370 
371 template<typename XprType, typename CastType> struct cast_return_type
372 {
373  typedef typename XprType::Scalar CurrentScalarType;
374  typedef typename remove_all<CastType>::type _CastType;
375  typedef typename _CastType::Scalar NewScalarType;
376  typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
377  const XprType&,CastType>::type type;
378 };
379 
380 template <typename A, typename B> struct promote_storage_type;
381 
382 template <typename A> struct promote_storage_type<A,A>
383 {
384  typedef A ret;
385 };
386 
390 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
391 struct plain_row_type
392 {
393  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
394  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
395  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
396  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
397 
398  typedef typename conditional<
399  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
400  MatrixRowType,
401  ArrayRowType
402  >::type type;
403 };
404 
405 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
406 struct plain_col_type
407 {
408  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
409  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
410  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
411  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
412 
413  typedef typename conditional<
414  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
415  MatrixColType,
416  ArrayColType
417  >::type type;
418 };
419 
420 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
421 struct plain_diag_type
422 {
423  enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
424  max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
425  };
426  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
427  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
428 
429  typedef typename conditional<
430  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
431  MatrixDiagType,
432  ArrayDiagType
433  >::type type;
434 };
435 
436 template<typename ExpressionType>
437 struct is_lvalue
438 {
439  enum { value = !bool(is_const<ExpressionType>::value) &&
440  bool(traits<ExpressionType>::Flags & LvalueBit) };
441 };
442 
443 } // end namespace internal
444 
445 } // end namespace Eigen
446 
447 #endif // EIGEN_XPRHELPER_H