Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
Ref.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2012 Gael Guennebaud <[email protected]>
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
16namespace Eigen {
17
18namespace internal {
19
20template <typename PlainObjectType_, int Options_, typename StrideType_>
21struct 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_,
27 Flags = traits<Map<PlainObjectType_, Options_, StrideType_> >::Flags | NestByRefBit,
28 Alignment = traits<Map<PlainObjectType_, Options_, StrideType_> >::Alignment,
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,
37 HasDirectAccess = internal::has_direct_access<Derived>::ret,
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
54 ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
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
62template <typename Derived>
63struct traits<RefBase<Derived> > : public traits<Derived> {};
64
65} // namespace internal
66
67template <typename Derived>
68class RefBase : public MapBase<Derived> {
69 typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType;
70 typedef typename internal::traits<Derived>::StrideType StrideType;
71
72 public:
73 typedef MapBase<Derived> Base;
74 EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
75
76 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const {
77 return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
78 }
79
80 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const {
81 return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
82 : IsVectorAtCompileTime ? this->size()
83 : int(Flags) & RowMajorBit ? this->cols()
84 : this->rows();
85 }
86
87 EIGEN_DEVICE_FUNC RefBase()
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
94 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase)
95
96 protected:
97 typedef Stride<StrideType::OuterStrideAtCompileTime, StrideType::InnerStrideAtCompileTime> StrideBase;
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.
103 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols,
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.
114 EIGEN_STATIC_ASSERT(EIGEN_PREDICATE_SAME_MATRIX_SIZE(PlainObjectType, Expression)
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
195 StrideBase m_stride;
196};
197
263template <typename PlainObjectType, int Options, typename StrideType>
264class Ref : public RefBase<Ref<PlainObjectType, Options, StrideType> > {
265 private:
266 typedef internal::traits<Ref> Traits;
267 template <typename Derived>
268 EIGEN_DEVICE_FUNC inline Ref(
269 const PlainObjectBase<Derived>& expr,
270 std::enable_if_t<bool(Traits::template match<Derived>::MatchAtCompileTime), Derived>* = 0);
271
272 public:
273 typedef RefBase<Ref> Base;
274 EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
275
276#ifndef EIGEN_PARSED_BY_DOXYGEN
277 template <typename Derived>
278 EIGEN_DEVICE_FUNC inline Ref(
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>
288 EIGEN_DEVICE_FUNC inline Ref(
289 const DenseBase<Derived>& expr,
290 std::enable_if_t<bool(Traits::template match<Derived>::MatchAtCompileTime), Derived>* = 0)
291#else
293 template <typename Derived>
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
306 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
307};
308
309// this is the const ref version
310template <typename TPlainObjectType, int Options, typename StrideType>
311class Ref<const TPlainObjectType, Options, StrideType>
312 : public RefBase<Ref<const TPlainObjectType, Options, StrideType> > {
313 typedef internal::traits<Ref> Traits;
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:
326 typedef RefBase<Ref> Base;
327 EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
328
329 template <typename Derived>
330 EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr,
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)) {
365 construct(expr, internal::false_type());
366 }
367 }
368
369 template <typename Expression>
370 EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::false_type) {
371 internal::call_assignment_no_alias(m_object, expr, internal::assign_op<Scalar, Scalar>());
372 const bool success = Base::construct(m_object);
373 EIGEN_ONLY_USED_FOR_DEBUG(success)
374 eigen_assert(success);
375 }
376
377 protected:
378 TPlainObjectType m_object;
379};
380
381} // end namespace Eigen
382
383#endif // EIGEN_REF_H
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:44
Dense storage base class for matrices and arrays.
Definition PlainObjectBase.h:121
A matrix or vector expression mapping an existing expression.
Definition Ref.h:264
Ref(DenseBase< Derived > &expr)
Definition Ref.h:294
EIGEN_CONSTEXPR Index inner() const
Definition Stride.h:76
EIGEN_CONSTEXPR Index outer() const
Definition Stride.h:74
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition Core:137
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