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 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef EIGEN_XPRHELPER_H
27 #define EIGEN_XPRHELPER_H
28 
29 // just a workaround because GCC seems to not really like empty structs
30 // FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled
31 // so currently we simply disable this optimization for gcc 4.3
32 #if (defined __GNUG__) && !((__GNUC__==4) && (__GNUC_MINOR__==3))
33  #define EIGEN_EMPTY_STRUCT_CTOR(X) \
34  EIGEN_STRONG_INLINE X() {} \
35  EIGEN_STRONG_INLINE X(const X& ) {}
36 #else
37  #define EIGEN_EMPTY_STRUCT_CTOR(X)
38 #endif
39 
40 namespace Eigen {
41 
43 
44 namespace internal {
45 
46 //classes inheriting no_assignment_operator don't generate a default operator=.
47 class no_assignment_operator
48 {
49  private:
50  no_assignment_operator& operator=(const no_assignment_operator&);
51 };
52 
54 template<typename I1, typename I2>
55 struct promote_index_type
56 {
57  typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
58 };
59 
64 template<typename T, int Value> class variable_if_dynamic
65 {
66  public:
67  EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
68  explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); }
69  static T value() { return T(Value); }
70  void setValue(T) {}
71 };
72 
73 template<typename T> class variable_if_dynamic<T, Dynamic>
74 {
75  T m_value;
76  variable_if_dynamic() { assert(false); }
77  public:
78  explicit variable_if_dynamic(T value) : m_value(value) {}
79  T value() const { return m_value; }
80  void setValue(T value) { m_value = value; }
81 };
82 
83 template<typename T> struct functor_traits
84 {
85  enum
86  {
87  Cost = 10,
88  PacketAccess = false
89  };
90 };
91 
92 template<typename T> struct packet_traits;
93 
94 template<typename T> struct unpacket_traits
95 {
96  typedef T type;
97  enum {size=1};
98 };
99 
100 template<typename _Scalar, int _Rows, int _Cols,
101  int _Options = AutoAlign |
102  ( (_Rows==1 && _Cols!=1) ? RowMajor
103  : (_Cols==1 && _Rows!=1) ? ColMajor
105  int _MaxRows = _Rows,
106  int _MaxCols = _Cols
107 > class make_proper_matrix_type
108 {
109  enum {
110  IsColVector = _Cols==1 && _Rows!=1,
111  IsRowVector = _Rows==1 && _Cols!=1,
112  Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
113  : IsRowVector ? (_Options | RowMajor) & ~ColMajor
114  : _Options
115  };
116  public:
118 };
119 
120 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
121 class compute_matrix_flags
122 {
123  enum {
124  row_major_bit = Options&RowMajor ? RowMajorBit : 0,
125  is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic,
126 
127  aligned_bit =
128  (
129  ((Options&DontAlign)==0)
130  && (
131 #if EIGEN_ALIGN_STATICALLY
132  ((!is_dynamic_size_storage) && (((MaxCols*MaxRows*int(sizeof(Scalar))) % 16) == 0))
133 #else
134  0
135 #endif
136 
137  ||
138 
139 #if EIGEN_ALIGN
140  is_dynamic_size_storage
141 #else
142  0
143 #endif
144 
145  )
146  ) ? AlignedBit : 0,
147  packet_access_bit = packet_traits<Scalar>::Vectorizable && aligned_bit ? PacketAccessBit : 0
148  };
149 
150  public:
151  enum { ret = LinearAccessBit | LvalueBit | DirectAccessBit | NestByRefBit | packet_access_bit | row_major_bit | aligned_bit };
152 };
153 
154 template<int _Rows, int _Cols> struct size_at_compile_time
155 {
156  enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
157 };
158 
159 /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
160  * whereas eval is a const reference in the case of a matrix
161  */
162 
163 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
164 template<typename T, typename BaseClassType> struct plain_matrix_type_dense;
165 template<typename T> struct plain_matrix_type<T,Dense>
166 {
167  typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind>::type type;
168 };
169 
170 template<typename T> struct plain_matrix_type_dense<T,MatrixXpr>
171 {
178  > type;
179 };
180 
181 template<typename T> struct plain_matrix_type_dense<T,ArrayXpr>
182 {
189  > type;
190 };
191 
192 /* eval : the return type of eval(). For matrices, this is just a const reference
193  * in order to avoid a useless copy
194  */
195 
196 template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
197 
198 template<typename T> struct eval<T,Dense>
199 {
200  typedef typename plain_matrix_type<T>::type type;
201 // typedef typename T::PlainObject type;
202 // typedef T::Matrix<typename traits<T>::Scalar,
203 // traits<T>::RowsAtCompileTime,
204 // traits<T>::ColsAtCompileTime,
205 // AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
206 // traits<T>::MaxRowsAtCompileTime,
207 // traits<T>::MaxColsAtCompileTime
208 // > type;
209 };
210 
211 // for matrices, no need to evaluate, just use a const reference to avoid a useless copy
212 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
213 struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
214 {
216 };
217 
218 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
219 struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
220 {
222 };
223 
224 
225 
226 /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
227  */
228 template<typename T> struct plain_matrix_type_column_major
229 {
230  enum { Rows = traits<T>::RowsAtCompileTime,
234  };
236  Rows,
237  Cols,
238  (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
239  MaxRows,
240  MaxCols
241  > type;
242 };
243 
244 /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
245  */
246 template<typename T> struct plain_matrix_type_row_major
247 {
248  enum { Rows = traits<T>::RowsAtCompileTime,
252  };
254  Rows,
255  Cols,
256  (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
257  MaxRows,
258  MaxCols
259  > type;
260 };
261 
262 // we should be able to get rid of this one too
263 template<typename T> struct must_nest_by_value { enum { ret = false }; };
264 
268 template <typename T>
269 struct ref_selector
270 {
271  typedef typename conditional<
273  T const&,
274  const T
275  >::type type;
276 };
277 
279 template<typename T1, typename T2>
280 struct transfer_constness
281 {
282  typedef typename conditional<
283  bool(internal::is_const<T1>::value),
284  typename internal::add_const_on_value_type<T2>::type,
285  T2
286  >::type type;
287 };
288 
309 template<typename T, int n=1, typename PlainObject = typename eval<T>::type> struct nested
310 {
311  enum {
312  // for the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values.
313  // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values.
314  // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues
315  // (poor choice of temporaries).
316  // it's important that this value can still be squared without integer overflowing.
317  DynamicAsInteger = 10000,
318  ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
319  ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? DynamicAsInteger : ScalarReadCost,
320  CoeffReadCost = traits<T>::CoeffReadCost,
321  CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? DynamicAsInteger : CoeffReadCost,
322  NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n,
323  CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger,
324  CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger
325  };
326 
327  typedef typename conditional<
329  int(CostEvalAsInteger) < int(CostNoEvalAsInteger)
330  ),
331  PlainObject,
332  typename ref_selector<T>::type
333  >::type type;
334 };
335 
336 template<typename T>
337 T* const_cast_ptr(const T* ptr)
338 {
339  return const_cast<T*>(ptr);
340 }
341 
342 template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
343 struct dense_xpr_base
344 {
345  /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
346 };
347 
348 template<typename Derived>
349 struct dense_xpr_base<Derived, MatrixXpr>
350 {
351  typedef MatrixBase<Derived> type;
352 };
353 
354 template<typename Derived>
355 struct dense_xpr_base<Derived, ArrayXpr>
356 {
357  typedef ArrayBase<Derived> type;
358 };
359 
362 template<typename Derived,typename Scalar,typename OtherScalar,
363  bool EnableIt = !is_same<Scalar,OtherScalar>::value >
364 struct special_scalar_op_base : public DenseCoeffsBase<Derived>
365 {
366  // dummy operator* so that the
367  // "using special_scalar_op_base::operator*" compiles
368  void operator*() const;
369 };
370 
371 template<typename Derived,typename Scalar,typename OtherScalar>
372 struct special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCoeffsBase<Derived>
373 {
374  const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
375  operator*(const OtherScalar& scalar) const
376  {
377  return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
378  (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar));
379  }
380 
381  inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
382  operator*(const OtherScalar& scalar, const Derived& matrix)
383  { return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); }
384 };
385 
386 template<typename XprType, typename CastType> struct cast_return_type
387 {
388  typedef typename XprType::Scalar CurrentScalarType;
389  typedef typename remove_all<CastType>::type _CastType;
390  typedef typename _CastType::Scalar NewScalarType;
391  typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
392  const XprType&,CastType>::type type;
393 };
394 
395 template <typename A, typename B> struct promote_storage_type;
396 
397 template <typename A> struct promote_storage_type<A,A>
398 {
399  typedef A ret;
400 };
401 
405 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
406 struct plain_row_type
407 {
408  typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
409  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
410  typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
411  ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
412 
413  typedef typename conditional<
414  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
415  MatrixRowType,
416  ArrayRowType
417  >::type type;
418 };
419 
420 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
421 struct plain_col_type
422 {
423  typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
424  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
425  typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
426  ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
427 
428  typedef typename conditional<
429  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
430  MatrixColType,
431  ArrayColType
432  >::type type;
433 };
434 
435 template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
436 struct plain_diag_type
437 {
438  enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
439  max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
440  };
441  typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
442  typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
443 
444  typedef typename conditional<
445  is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
446  MatrixDiagType,
447  ArrayDiagType
448  >::type type;
449 };
450 
451 template<typename ExpressionType>
452 struct is_lvalue
453 {
454  enum { value = !bool(is_const<ExpressionType>::value) &&
456 };
457 
458 } // end namespace internal
459 
460 } // end namespace Eigen
461 
462 #endif // EIGEN_XPRHELPER_H