Ref.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) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_REF_H
11 #define EIGEN_REF_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 template <typename PlainObjectType_, int Options_, typename StrideType_>
21 struct traits<Ref<PlainObjectType_, Options_, StrideType_> >
22  : public traits<Map<PlainObjectType_, Options_, StrideType_> > {
23  typedef PlainObjectType_ PlainObjectType;
24  typedef StrideType_ StrideType;
25  enum {
26  Options = Options_,
29  InnerStrideAtCompileTime = traits<Map<PlainObjectType_, Options_, StrideType_> >::InnerStrideAtCompileTime,
30  OuterStrideAtCompileTime = traits<Map<PlainObjectType_, Options_, StrideType_> >::OuterStrideAtCompileTime
31  };
32 
33  template <typename Derived>
34  struct match {
35  enum {
36  IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime,
38  StorageOrderMatch =
39  IsVectorAtCompileTime || ((PlainObjectType::Flags & RowMajorBit) == (Derived::Flags & RowMajorBit)),
40  InnerStrideMatch = int(InnerStrideAtCompileTime) == int(Dynamic) ||
41  int(InnerStrideAtCompileTime) == int(Derived::InnerStrideAtCompileTime) ||
42  (int(InnerStrideAtCompileTime) == 0 && int(Derived::InnerStrideAtCompileTime) == 1),
43  OuterStrideMatch = IsVectorAtCompileTime || int(OuterStrideAtCompileTime) == int(Dynamic) ||
44  int(OuterStrideAtCompileTime) == int(Derived::OuterStrideAtCompileTime),
45  // NOTE, this indirection of evaluator<Derived>::Alignment is needed
46  // to workaround a very strange bug in MSVC related to the instantiation
47  // of has_*ary_operator in evaluator<CwiseNullaryOp>.
48  // This line is surprisingly very sensitive. For instance, simply adding parenthesis
49  // as "DerivedAlignment = (int(evaluator<Derived>::Alignment))," will make MSVC fail...
50  DerivedAlignment = int(evaluator<Derived>::Alignment),
51  AlignmentMatch = (int(traits<PlainObjectType>::Alignment) == int(Unaligned)) ||
52  (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should
53  // be replaced by the required alignment
55  MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch &&
56  AlignmentMatch && ScalarTypeMatch
57  };
58  typedef std::conditional_t<MatchAtCompileTime, internal::true_type, internal::false_type> type;
59  };
60 };
61 
62 template <typename Derived>
63 struct traits<RefBase<Derived> > : public traits<Derived> {};
64 
65 } // namespace internal
66 
67 template <typename Derived>
68 class RefBase : public MapBase<Derived> {
71 
72  public:
75 
77  return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
78  }
79 
81  return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
82  : IsVectorAtCompileTime ? this->size()
83  : int(Flags) & RowMajorBit ? this->cols()
84  : this->rows();
85  }
86 
88  : Base(0, RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime,
89  ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime),
90  // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values:
91  m_stride(StrideType::OuterStrideAtCompileTime == Dynamic ? 0 : StrideType::OuterStrideAtCompileTime,
92  StrideType::InnerStrideAtCompileTime == Dynamic ? 0 : StrideType::InnerStrideAtCompileTime) {}
93 
95 
96  protected:
98 
99  // Resolves inner stride if default 0.
100  static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveInnerStride(Index inner) { return inner == 0 ? 1 : inner; }
101 
102  // Resolves outer stride if default 0.
104  bool isVectorAtCompileTime, bool isRowMajor) {
105  return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols : isRowMajor ? inner * cols : inner * rows : outer;
106  }
107 
108  // Returns true if construction is valid, false if there is a stride mismatch,
109  // and fails if there is a size mismatch.
110  template <typename Expression>
111  EIGEN_DEVICE_FUNC bool construct(Expression& expr) {
112  // Check matrix sizes. If this is a compile-time vector, we do allow
113  // implicitly transposing.
115  // If it is a vector, the transpose sizes might match.
116  || (PlainObjectType::IsVectorAtCompileTime &&
117  ((int(PlainObjectType::RowsAtCompileTime) == Eigen::Dynamic ||
118  int(Expression::ColsAtCompileTime) == Eigen::Dynamic ||
119  int(PlainObjectType::RowsAtCompileTime) == int(Expression::ColsAtCompileTime)) &&
120  (int(PlainObjectType::ColsAtCompileTime) == Eigen::Dynamic ||
121  int(Expression::RowsAtCompileTime) == Eigen::Dynamic ||
122  int(PlainObjectType::ColsAtCompileTime) == int(Expression::RowsAtCompileTime)))),
123  YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
124 
125  // Determine runtime rows and columns.
126  Index rows = expr.rows();
127  Index cols = expr.cols();
128  if (PlainObjectType::RowsAtCompileTime == 1) {
129  eigen_assert(expr.rows() == 1 || expr.cols() == 1);
130  rows = 1;
131  cols = expr.size();
132  } else if (PlainObjectType::ColsAtCompileTime == 1) {
133  eigen_assert(expr.rows() == 1 || expr.cols() == 1);
134  rows = expr.size();
135  cols = 1;
136  }
137  // Verify that the sizes are valid.
138  eigen_assert((PlainObjectType::RowsAtCompileTime == Dynamic) || (PlainObjectType::RowsAtCompileTime == rows));
139  eigen_assert((PlainObjectType::ColsAtCompileTime == Dynamic) || (PlainObjectType::ColsAtCompileTime == cols));
140 
141  // If this is a vector, we might be transposing, which means that stride should swap.
142  const bool transpose = PlainObjectType::IsVectorAtCompileTime && (rows != expr.rows());
143  // If the storage format differs, we also need to swap the stride.
144  const bool row_major = ((PlainObjectType::Flags)&RowMajorBit) != 0;
145  const bool expr_row_major = (Expression::Flags & RowMajorBit) != 0;
146  const bool storage_differs = (row_major != expr_row_major);
147 
148  const bool swap_stride = (transpose != storage_differs);
149 
150  // Determine expr's actual strides, resolving any defaults if zero.
151  const Index expr_inner_actual = resolveInnerStride(expr.innerStride());
152  const Index expr_outer_actual = resolveOuterStride(expr_inner_actual, expr.outerStride(), expr.rows(), expr.cols(),
153  Expression::IsVectorAtCompileTime != 0, expr_row_major);
154 
155  // If this is a column-major row vector or row-major column vector, the inner-stride
156  // is arbitrary, so set it to either the compile-time inner stride or 1.
157  const bool row_vector = (rows == 1);
158  const bool col_vector = (cols == 1);
159  const Index inner_stride =
160  ((!row_major && row_vector) || (row_major && col_vector))
161  ? (StrideType::InnerStrideAtCompileTime > 0 ? Index(StrideType::InnerStrideAtCompileTime) : 1)
162  : swap_stride ? expr_outer_actual
163  : expr_inner_actual;
164 
165  // If this is a column-major column vector or row-major row vector, the outer-stride
166  // is arbitrary, so set it to either the compile-time outer stride or vector size.
167  const Index outer_stride =
168  ((!row_major && col_vector) || (row_major && row_vector))
169  ? (StrideType::OuterStrideAtCompileTime > 0 ? Index(StrideType::OuterStrideAtCompileTime)
170  : rows * cols * inner_stride)
171  : swap_stride ? expr_inner_actual
172  : expr_outer_actual;
173 
174  // Check if given inner/outer strides are compatible with compile-time strides.
175  const bool inner_valid = (StrideType::InnerStrideAtCompileTime == Dynamic) ||
176  (resolveInnerStride(Index(StrideType::InnerStrideAtCompileTime)) == inner_stride);
177  if (!inner_valid) {
178  return false;
179  }
180 
181  const bool outer_valid =
182  (StrideType::OuterStrideAtCompileTime == Dynamic) ||
183  (resolveOuterStride(inner_stride, Index(StrideType::OuterStrideAtCompileTime), rows, cols,
184  PlainObjectType::IsVectorAtCompileTime != 0, row_major) == outer_stride);
185  if (!outer_valid) {
186  return false;
187  }
188 
189  internal::construct_at<Base>(this, expr.data(), rows, cols);
190  internal::construct_at(&m_stride, (StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride,
191  (StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride);
192  return true;
193  }
194 
196 };
197 
263 template <typename PlainObjectType, int Options, typename StrideType>
264 class Ref : public RefBase<Ref<PlainObjectType, Options, StrideType> > {
265  private:
267  template <typename Derived>
269  const PlainObjectBase<Derived>& expr,
270  std::enable_if_t<bool(Traits::template match<Derived>::MatchAtCompileTime), Derived>* = 0);
271 
272  public:
275 
276 #ifndef EIGEN_PARSED_BY_DOXYGEN
277  template <typename Derived>
280  std::enable_if_t<bool(Traits::template match<Derived>::MatchAtCompileTime), Derived>* = 0) {
281  EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
282  // Construction must pass since we will not create temporary storage in the non-const case.
283  const bool success = Base::construct(expr.derived());
284  EIGEN_UNUSED_VARIABLE(success)
285  eigen_assert(success);
286  }
287  template <typename Derived>
289  const DenseBase<Derived>& expr,
290  std::enable_if_t<bool(Traits::template match<Derived>::MatchAtCompileTime), Derived>* = 0)
291 #else
293  template <typename Derived>
294  inline Ref(DenseBase<Derived>& expr)
295 #endif
296  {
297  EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
298  EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
299  EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase, THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
300  // Construction must pass since we will not create temporary storage in the non-const case.
301  const bool success = Base::construct(expr.const_cast_derived());
302  EIGEN_UNUSED_VARIABLE(success)
303  eigen_assert(success);
304  }
305 
307 };
308 
309 // this is the const ref version
310 template <typename TPlainObjectType, int Options, typename StrideType>
311 class Ref<const TPlainObjectType, Options, StrideType>
312  : public RefBase<Ref<const TPlainObjectType, Options, StrideType> > {
314 
315  static constexpr bool may_map_m_object_successfully =
316  (static_cast<int>(StrideType::InnerStrideAtCompileTime) == 0 ||
317  static_cast<int>(StrideType::InnerStrideAtCompileTime) == 1 ||
318  static_cast<int>(StrideType::InnerStrideAtCompileTime) == Dynamic) &&
319  (TPlainObjectType::IsVectorAtCompileTime || static_cast<int>(StrideType::OuterStrideAtCompileTime) == 0 ||
320  static_cast<int>(StrideType::OuterStrideAtCompileTime) == Dynamic ||
321  static_cast<int>(StrideType::OuterStrideAtCompileTime) ==
322  static_cast<int>(TPlainObjectType::InnerSizeAtCompileTime) ||
323  static_cast<int>(TPlainObjectType::InnerSizeAtCompileTime) == Dynamic);
324 
325  public:
328 
329  template <typename Derived>
331  std::enable_if_t<bool(Traits::template match<Derived>::ScalarTypeMatch), Derived>* = 0) {
332  // std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << ","
333  // << match_helper<Derived>::InnerStrideMatch << "\n"; std::cout << int(StrideType::OuterStrideAtCompileTime)
334  // << " - " << int(Derived::OuterStrideAtCompileTime) << "\n"; std::cout <<
335  // int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
336  EIGEN_STATIC_ASSERT(Traits::template match<Derived>::type::value || may_map_m_object_successfully,
337  STORAGE_LAYOUT_DOES_NOT_MATCH);
338  construct(expr.derived(), typename Traits::template match<Derived>::type());
339  }
340 
341  EIGEN_DEVICE_FUNC inline Ref(const Ref& other) : Base(other) {
342  // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
343  }
344 
345  EIGEN_DEVICE_FUNC inline Ref(Ref&& other) {
346  if (other.data() == other.m_object.data()) {
347  m_object = std::move(other.m_object);
348  Base::construct(m_object);
349  } else
350  Base::construct(other);
351  }
352 
353  template <typename OtherRef>
354  EIGEN_DEVICE_FUNC inline Ref(const RefBase<OtherRef>& other) {
355  EIGEN_STATIC_ASSERT(Traits::template match<OtherRef>::type::value || may_map_m_object_successfully,
356  STORAGE_LAYOUT_DOES_NOT_MATCH);
357  construct(other.derived(), typename Traits::template match<OtherRef>::type());
358  }
359 
360  protected:
361  template <typename Expression>
362  EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::true_type) {
363  // Check if we can use the underlying expr's storage directly, otherwise call the copy version.
364  if (!Base::construct(expr)) {
366  }
367  }
368 
369  template <typename Expression>
370  EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::false_type) {
372  const bool success = Base::construct(m_object);
374  eigen_assert(success);
375  }
376 
377  protected:
378  TPlainObjectType m_object;
379 };
380 
381 } // end namespace Eigen
382 
383 #endif // EIGEN_REF_H
#define EIGEN_CONSTEXPR
Definition: Macros.h:758
#define EIGEN_UNUSED_VARIABLE(var)
Definition: Macros.h:966
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:892
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
Definition: Macros.h:922
#define EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
Definition: Macros.h:1171
#define eigen_assert(x)
Definition: Macros.h:910
#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived)
Macro to manually inherit assignment operators. This is necessary, because the implicitly defined ass...
Definition: Macros.h:1126
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0, TYPE1)
Definition: StaticAssert.h:66
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
Base class for all dense matrices, vectors, and arrays.
Definition: DenseBase.h:44
Definition: ForwardDeclarations.h:150
Definition: PlainObjectBase.h:121
Definition: Ref.h:68
internal::traits< Derived >::PlainObjectType PlainObjectType
Definition: Ref.h:69
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index innerStride() const
Definition: Ref.h:76
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerStride() const
Definition: Ref.h:80
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveInnerStride(Index inner)
Definition: Ref.h:100
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols, bool isVectorAtCompileTime, bool isRowMajor)
Definition: Ref.h:103
EIGEN_DEVICE_FUNC bool construct(Expression &expr)
Definition: Ref.h:111
EIGEN_DEVICE_FUNC RefBase()
Definition: Ref.h:87
internal::traits< Derived >::StrideType StrideType
Definition: Ref.h:70
Stride< StrideType::OuterStrideAtCompileTime, StrideType::InnerStrideAtCompileTime > StrideBase
Definition: Ref.h:97
StrideBase m_stride
Definition: Ref.h:195
MapBase< Derived > Base
Definition: Ref.h:73
EIGEN_DEVICE_FUNC Ref(const DenseBase< Derived > &expr, std::enable_if_t< bool(Traits::template match< Derived >::ScalarTypeMatch), Derived > *=0)
Definition: Ref.h:330
internal::traits< Ref > Traits
Definition: Ref.h:313
EIGEN_DEVICE_FUNC Ref(const RefBase< OtherRef > &other)
Definition: Ref.h:354
TPlainObjectType m_object
Definition: Ref.h:378
EIGEN_DEVICE_FUNC void construct(const Expression &expr, internal::false_type)
Definition: Ref.h:370
EIGEN_DEVICE_FUNC void construct(const Expression &expr, internal::true_type)
Definition: Ref.h:362
EIGEN_DEVICE_FUNC Ref(Ref &&other)
Definition: Ref.h:345
EIGEN_DEVICE_FUNC Ref(const Ref &other)
Definition: Ref.h:341
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:264
EIGEN_DEVICE_FUNC Ref(PlainObjectBase< Derived > &expr, std::enable_if_t< bool(Traits::template match< Derived >::MatchAtCompileTime), Derived > *=0)
Definition: Ref.h:278
internal::traits< Ref > Traits
Definition: Ref.h:266
RefBase< Ref > Base
Definition: Ref.h:273
EIGEN_DEVICE_FUNC Ref(const DenseBase< Derived > &expr, std::enable_if_t< bool(Traits::template match< Derived >::MatchAtCompileTime), Derived > *=0)
Definition: Ref.h:288
EIGEN_DEVICE_FUNC Ref(const PlainObjectBase< Derived > &expr, std::enable_if_t< bool(Traits::template match< Derived >::MatchAtCompileTime), Derived > *=0)
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outer() const
Definition: Stride.h:81
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index inner() const
Definition: Stride.h:83
@ Unaligned
Definition: Constants.h:235
const unsigned int RowMajorBit
Definition: Constants.h:70
bool match(const T &xpr, std::string ref, std::string str_xpr="")
Definition: indexed_view.cpp:29
return int(ret)+1
EIGEN_DEVICE_FUNC T * construct_at(T *p, Args &&... args)
Definition: Memory.h:1321
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
Definition: AssignEvaluator.h:812
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
squared absolute value
Definition: GlobalFunctions.h:87
const unsigned int NestByRefBit
Definition: Constants.h:173
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
const int Dynamic
Definition: Constants.h:25
Extend namespace for flags.
Definition: fsi_chan_precond_driver.cc:56
void transpose()
Definition: skew_symmetric_matrix3.cpp:135
type
Definition: compute_granudrum_aor.py:141
Definition: Eigen_Colamd.h:49
Template functor for scalar/packet assignment.
Definition: AssignmentFunctors.h:25
Definition: CoreEvaluators.h:104
Definition: Meta.h:97
Definition: ForwardDeclarations.h:31
Definition: XprHelper.h:819
Definition: Meta.h:205
std::conditional_t< MatchAtCompileTime, internal::true_type, internal::false_type > type
Definition: Ref.h:58
Definition: ForwardDeclarations.h:21
Definition: Meta.h:94