Eigen  5.0.1
 
Loading...
Searching...
No Matches
IndexedView.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2017 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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_INDEXED_VIEW_H
12#define EIGEN_INDEXED_VIEW_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <typename XprType, typename RowIndices, typename ColIndices>
22struct traits<IndexedView<XprType, RowIndices, ColIndices>> : traits<XprType> {
23 enum {
24 RowsAtCompileTime = int(IndexedViewHelper<RowIndices>::SizeAtCompileTime),
25 ColsAtCompileTime = int(IndexedViewHelper<ColIndices>::SizeAtCompileTime),
26 MaxRowsAtCompileTime = RowsAtCompileTime,
27 MaxColsAtCompileTime = ColsAtCompileTime,
28
29 XprTypeIsRowMajor = (int(traits<XprType>::Flags) & RowMajorBit) != 0,
30 IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1
31 : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0
32 : XprTypeIsRowMajor,
33
34 RowIncr = int(IndexedViewHelper<RowIndices>::IncrAtCompileTime),
35 ColIncr = int(IndexedViewHelper<ColIndices>::IncrAtCompileTime),
36 InnerIncr = IsRowMajor ? ColIncr : RowIncr,
37 OuterIncr = IsRowMajor ? RowIncr : ColIncr,
38
39 HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
40 XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType>::value)
41 : int(outer_stride_at_compile_time<XprType>::value),
42 XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType>::value)
43 : int(inner_stride_at_compile_time<XprType>::value),
44
45 InnerSize = XprTypeIsRowMajor ? ColsAtCompileTime : RowsAtCompileTime,
46 IsBlockAlike = InnerIncr == 1 && OuterIncr == 1,
47 IsInnerPannel =
48 HasSameStorageOrderAsXprType &&
49 std::is_same<AllRange<InnerSize>, std::conditional_t<XprTypeIsRowMajor, ColIndices, RowIndices>>::value,
50
51 InnerStrideAtCompileTime =
52 InnerIncr < 0 || InnerIncr == DynamicIndex || XprInnerStride == Dynamic || InnerIncr == Undefined
53 ? Dynamic
54 : XprInnerStride * InnerIncr,
55 OuterStrideAtCompileTime =
56 OuterIncr < 0 || OuterIncr == DynamicIndex || XprOuterstride == Dynamic || OuterIncr == Undefined
57 ? Dynamic
58 : XprOuterstride * OuterIncr,
59
60 ReturnAsScalar = is_single_range<RowIndices>::value && is_single_range<ColIndices>::value,
61 ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike,
62 ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock),
63
64 // FIXME: we deal with compile-time strides if and only if we have DirectAccessBit flag,
65 // but this is too strict regarding negative strides...
66 DirectAccessMask = (int(InnerIncr) != Undefined && int(OuterIncr) != Undefined && InnerIncr >= 0 && OuterIncr >= 0)
68 : 0,
69 FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
70 FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
71 FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
72 // IsRowMajor above pins a single-column view to column-major and a single-row view to
73 // row-major, so the nested expression's RowMajorBit must not be inherited on top of it.
74 Flags = (traits<XprType>::Flags & ((HereditaryBits & ~RowMajorBit) | DirectAccessMask)) | FlagsLvalueBit |
75 FlagsRowMajorBit | FlagsLinearAccessBit
76 };
77
78 using BlockType = Block<XprType, RowsAtCompileTime, ColsAtCompileTime, IsInnerPannel>;
79};
80
81template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind, bool DirectAccess>
82class IndexedViewImpl;
83
84} // namespace internal
85
124template <typename XprType, typename RowIndices, typename ColIndices>
125class IndexedView
126 : public internal::IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind,
127 (internal::traits<IndexedView<XprType, RowIndices, ColIndices>>::Flags &
128 DirectAccessBit) != 0> {
129 public:
130 using Base = typename internal::IndexedViewImpl<
131 XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind,
132 (internal::traits<IndexedView<XprType, RowIndices, ColIndices>>::Flags & DirectAccessBit) != 0>;
133 EIGEN_GENERIC_PUBLIC_INTERFACE(IndexedView)
134 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedView)
135
136 template <typename T0, typename T1>
137 IndexedView(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {}
138};
139
140namespace internal {
141
142// Generic API dispatcher
143template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind, bool DirectAccess>
144class IndexedViewImpl : public internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices>>::type {
145 public:
146 using Base = typename internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices>>::type;
147 using MatrixTypeNested = typename internal::ref_selector<XprType>::non_const_type;
148 using NestedExpression = internal::remove_all_t<XprType>;
149 using Scalar = typename XprType::Scalar;
150
151 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl)
152
153 template <typename T0, typename T1>
154 IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices)
155 : m_xpr(xpr), m_rowIndices(rowIndices), m_colIndices(colIndices) {}
156
158 Index rows() const { return IndexedViewHelper<RowIndices>::size(m_rowIndices); }
159
161 Index cols() const { return IndexedViewHelper<ColIndices>::size(m_colIndices); }
162
164 const internal::remove_all_t<XprType>& nestedExpression() const { return m_xpr; }
165
167 std::remove_reference_t<XprType>& nestedExpression() { return m_xpr; }
168
170 const RowIndices& rowIndices() const { return m_rowIndices; }
171
173 const ColIndices& colIndices() const { return m_colIndices; }
174
175 constexpr Scalar& coeffRef(Index rowId, Index colId) {
176 return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]);
177 }
178
179 constexpr const Scalar& coeffRef(Index rowId, Index colId) const {
180 return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]);
181 }
182
183 protected:
184 MatrixTypeNested m_xpr;
185 RowIndices m_rowIndices;
186 ColIndices m_colIndices;
187};
188
189template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind>
190class IndexedViewImpl<XprType, RowIndices, ColIndices, StorageKind, true>
191 : public IndexedViewImpl<XprType, RowIndices, ColIndices, StorageKind, false> {
192 public:
193 using Base = internal::IndexedViewImpl<XprType, RowIndices, ColIndices,
194 typename internal::traits<XprType>::StorageKind, false>;
195 using Derived = IndexedView<XprType, RowIndices, ColIndices>;
196
197 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl)
198
199 template <typename T0, typename T1>
200 IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {}
201
202 Index rowIncrement() const {
203 EIGEN_IF_CONSTEXPR (traits<Derived>::RowIncr != DynamicIndex && traits<Derived>::RowIncr != Undefined) {
204 return traits<Derived>::RowIncr;
205 }
206 return IndexedViewHelper<RowIndices>::incr(this->rowIndices());
207 }
208 Index colIncrement() const {
209 EIGEN_IF_CONSTEXPR (traits<Derived>::ColIncr != DynamicIndex && traits<Derived>::ColIncr != Undefined) {
210 return traits<Derived>::ColIncr;
211 }
212 return IndexedViewHelper<ColIndices>::incr(this->colIndices());
213 }
214
215 Index innerIncrement() const { return traits<Derived>::IsRowMajor ? colIncrement() : rowIncrement(); }
216
217 Index outerIncrement() const { return traits<Derived>::IsRowMajor ? rowIncrement() : colIncrement(); }
218
219 using ScalarWithConstIfNotLvalue =
220 std::conditional_t<is_lvalue<XprType>::value, std::decay_t<typename XprType::Scalar>,
221 const std::decay_t<typename XprType::Scalar>>;
222
223 ScalarWithConstIfNotLvalue* data() {
224 Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride();
225 Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride();
226 return this->nestedExpression().data() + row_offset + col_offset;
227 }
228
229 const std::decay_t<typename XprType::Scalar>* data() const {
230 Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride();
231 Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride();
232 return this->nestedExpression().data() + row_offset + col_offset;
233 }
234
235 EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept {
236 EIGEN_IF_CONSTEXPR (traits<Derived>::InnerStrideAtCompileTime != Dynamic) {
237 return traits<Derived>::InnerStrideAtCompileTime;
238 }
239 // A vector-shaped view need not share the nested storage order, so step along the view's own inner dimension.
240 return traits<Derived>::IsRowMajor ? colIncrement() * this->nestedExpression().colStride()
241 : rowIncrement() * this->nestedExpression().rowStride();
242 }
243
244 EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept {
245 EIGEN_IF_CONSTEXPR (traits<Derived>::OuterStrideAtCompileTime != Dynamic) {
246 return traits<Derived>::OuterStrideAtCompileTime;
247 }
248 return traits<Derived>::IsRowMajor ? rowIncrement() * this->nestedExpression().rowStride()
249 : colIncrement() * this->nestedExpression().colStride();
250 }
251};
252
253template <typename ArgType, typename RowIndices, typename ColIndices>
254struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
255 : evaluator_base<IndexedView<ArgType, RowIndices, ColIndices>> {
256 using XprType = IndexedView<ArgType, RowIndices, ColIndices>;
257
258 enum {
259 CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of row/col index */,
260
261 FlagsLinearAccessBit =
262 (traits<XprType>::RowsAtCompileTime == 1 || traits<XprType>::ColsAtCompileTime == 1) ? LinearAccessBit : 0,
263
264 FlagsRowMajorBit = traits<XprType>::FlagsRowMajorBit,
265
266 Flags = (evaluator<ArgType>::Flags & (HereditaryBits & ~RowMajorBit /*| LinearAccessBit | DirectAccessBit*/)) |
267 FlagsLinearAccessBit | FlagsRowMajorBit,
268
269 Alignment = 0
270 };
271
272 EIGEN_DEVICE_FUNC constexpr explicit unary_evaluator(const XprType& xpr)
273 : m_argImpl(xpr.nestedExpression()), m_xpr(xpr) {
274 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
275 }
276
277 using Scalar = typename XprType::Scalar;
278 using CoeffReturnType = typename XprType::CoeffReturnType;
279
280 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const {
281 eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() &&
282 m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
283 return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
284 }
285
286 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) {
287 eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() &&
288 m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
289 return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
290 }
291
292 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
293 EIGEN_STATIC_ASSERT_LVALUE(XprType)
294 Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
295 Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
296 eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() &&
297 m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
298 return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
299 }
300
301 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const {
302 Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
303 Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
304 eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() &&
305 m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
306 return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
307 }
308
309 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index index) const {
310 Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
311 Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
312 eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() &&
313 m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
314 return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
315 }
316
317 protected:
318 evaluator<ArgType> m_argImpl;
319 const XprType& m_xpr;
320};
321
322// Catch assignments to an IndexedView.
323template <typename ArgType, typename RowIndices, typename ColIndices>
324struct evaluator_assume_aliasing<IndexedView<ArgType, RowIndices, ColIndices>> : std::true_type {};
325
326} // end namespace internal
327
328} // end namespace Eigen
329
330#endif // EIGEN_INDEXED_VIEW_H
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
constexpr unsigned int LinearAccessBit
Definition Constants.h:134
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71