$darkmode
Eigen  5.0.1-dev
Reshaped.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2017 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2014 yoco <peter.xiau@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_RESHAPED_H
12 #define EIGEN_RESHAPED_H
13 
14 // IWYU pragma: private
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
48 namespace internal {
49 
50 template <typename XprType, int Rows, int Cols, int Order>
51 struct traits<Reshaped<XprType, Rows, Cols, Order> > : traits<XprType> {
52  typedef typename traits<XprType>::Scalar Scalar;
53  typedef typename traits<XprType>::StorageKind StorageKind;
54  typedef typename traits<XprType>::XprKind XprKind;
55  enum {
56  MatrixRows = traits<XprType>::RowsAtCompileTime,
57  MatrixCols = traits<XprType>::ColsAtCompileTime,
58  RowsAtCompileTime = Rows,
59  ColsAtCompileTime = Cols,
60  MaxRowsAtCompileTime = Rows,
61  MaxColsAtCompileTime = Cols,
62  XpxStorageOrder = ((int(traits<XprType>::Flags) & RowMajorBit) == RowMajorBit) ? RowMajor : ColMajor,
63  ReshapedStorageOrder = (RowsAtCompileTime == 1 && ColsAtCompileTime != 1) ? RowMajor
64  : (ColsAtCompileTime == 1 && RowsAtCompileTime != 1) ? ColMajor
65  : XpxStorageOrder,
66  HasSameStorageOrderAsXprType = (ReshapedStorageOrder == XpxStorageOrder),
67  InnerSize = (ReshapedStorageOrder == int(RowMajor)) ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
68  InnerStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType>::ret) : Dynamic,
69  OuterStrideAtCompileTime = Dynamic,
70 
71  HasDirectAccess = internal::has_direct_access<XprType>::ret && (Order == int(XpxStorageOrder)) &&
72  ((evaluator<XprType>::Flags & LinearAccessBit) == LinearAccessBit),
73 
74  MaskPacketAccessBit =
75  (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0) && (InnerStrideAtCompileTime == 1)
77  : 0,
78  // MaskAlignedBit = ((OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16)
79  // == 0)) ? AlignedBit : 0,
80  FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
81  FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
82  FlagsRowMajorBit = (ReshapedStorageOrder == int(RowMajor)) ? RowMajorBit : 0,
83  FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0,
84  Flags0 = traits<XprType>::Flags & ((HereditaryBits & ~RowMajorBit) | MaskPacketAccessBit),
85 
86  Flags = (Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit | FlagsDirectAccessBit)
87  };
88 };
89 
90 template <typename XprType, int Rows, int Cols, int Order, bool HasDirectAccess>
91 class ReshapedImpl_dense;
92 
93 } // end namespace internal
94 
95 template <typename XprType, int Rows, int Cols, int Order, typename StorageKind>
96 class ReshapedImpl;
97 
98 template <typename XprType, int Rows, int Cols, int Order>
99 class Reshaped : public ReshapedImpl<XprType, Rows, Cols, Order, typename internal::traits<XprType>::StorageKind> {
100  typedef ReshapedImpl<XprType, Rows, Cols, Order, typename internal::traits<XprType>::StorageKind> Impl;
101 
102  public:
103  // typedef typename Impl::Base Base;
104  typedef Impl Base;
105  EIGEN_GENERIC_PUBLIC_INTERFACE(Reshaped)
106  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reshaped)
107 
108 
110  EIGEN_DEVICE_FUNC inline Reshaped(XprType& xpr) : Impl(xpr) {
111  EIGEN_STATIC_ASSERT(RowsAtCompileTime != Dynamic && ColsAtCompileTime != Dynamic,
112  THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
113  eigen_assert(Rows * Cols == xpr.rows() * xpr.cols());
114  }
115 
118  EIGEN_DEVICE_FUNC inline Reshaped(XprType& xpr, Index reshapeRows, Index reshapeCols)
119  : Impl(xpr, reshapeRows, reshapeCols) {
120  eigen_assert((RowsAtCompileTime == Dynamic || RowsAtCompileTime == reshapeRows) &&
121  (ColsAtCompileTime == Dynamic || ColsAtCompileTime == reshapeCols));
122  eigen_assert(reshapeRows * reshapeCols == xpr.rows() * xpr.cols());
123  }
124 };
125 
126 // The generic default implementation for dense reshape simply forward to the internal::ReshapedImpl_dense
127 // that must be specialized for direct and non-direct access...
128 template <typename XprType, int Rows, int Cols, int Order>
129 class ReshapedImpl<XprType, Rows, Cols, Order, Dense>
130  : public internal::ReshapedImpl_dense<XprType, Rows, Cols, Order,
131  internal::traits<Reshaped<XprType, Rows, Cols, Order> >::HasDirectAccess> {
132  typedef internal::ReshapedImpl_dense<XprType, Rows, Cols, Order,
133  internal::traits<Reshaped<XprType, Rows, Cols, Order> >::HasDirectAccess>
134  Impl;
135 
136  public:
137  typedef Impl Base;
138  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl)
139  EIGEN_DEVICE_FUNC inline ReshapedImpl(XprType& xpr) : Impl(xpr) {}
140  EIGEN_DEVICE_FUNC inline ReshapedImpl(XprType& xpr, Index reshapeRows, Index reshapeCols)
141  : Impl(xpr, reshapeRows, reshapeCols) {}
142 };
143 
144 namespace internal {
145 
147 template <typename XprType, int Rows, int Cols, int Order>
148 class ReshapedImpl_dense<XprType, Rows, Cols, Order, false>
149  : public internal::dense_xpr_base<Reshaped<XprType, Rows, Cols, Order> >::type {
150  typedef Reshaped<XprType, Rows, Cols, Order> ReshapedType;
151 
152  public:
153  typedef typename internal::dense_xpr_base<ReshapedType>::type Base;
154  EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType)
155  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense)
156 
157  typedef typename internal::ref_selector<XprType>::non_const_type MatrixTypeNested;
158  typedef internal::remove_all_t<XprType> NestedExpression;
159 
160  class InnerIterator;
161 
164  EIGEN_DEVICE_FUNC inline ReshapedImpl_dense(XprType& xpr) : m_xpr(xpr), m_rows(Rows), m_cols(Cols) {}
165 
168  EIGEN_DEVICE_FUNC inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols)
169  : m_xpr(xpr), m_rows(nRows), m_cols(nCols) {}
170 
171  EIGEN_DEVICE_FUNC Index rows() const { return m_rows; }
172  EIGEN_DEVICE_FUNC Index cols() const { return m_cols; }
173 
174 #ifdef EIGEN_PARSED_BY_DOXYGEN
175 
176  EIGEN_DEVICE_FUNC constexpr const Scalar* data() const;
177  EIGEN_DEVICE_FUNC inline Index innerStride() const;
178  EIGEN_DEVICE_FUNC inline Index outerStride() const;
179 #endif
180 
182  EIGEN_DEVICE_FUNC const internal::remove_all_t<XprType>& nestedExpression() const { return m_xpr; }
183 
185  EIGEN_DEVICE_FUNC std::remove_reference_t<XprType>& nestedExpression() { return m_xpr; }
186 
187  protected:
188  MatrixTypeNested m_xpr;
189  const internal::variable_if_dynamic<Index, Rows> m_rows;
190  const internal::variable_if_dynamic<Index, Cols> m_cols;
191 };
192 
194 template <typename XprType, int Rows, int Cols, int Order>
195 class ReshapedImpl_dense<XprType, Rows, Cols, Order, true> : public MapBase<Reshaped<XprType, Rows, Cols, Order> > {
196  typedef Reshaped<XprType, Rows, Cols, Order> ReshapedType;
197  typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested;
198 
199  public:
200  typedef MapBase<ReshapedType> Base;
201  EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType)
202  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense)
203 
204 
206  EIGEN_DEVICE_FUNC inline ReshapedImpl_dense(XprType& xpr) : Base(xpr.data()), m_xpr(xpr) {}
207 
210  EIGEN_DEVICE_FUNC inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols)
211  : Base(xpr.data(), nRows, nCols), m_xpr(xpr) {}
212 
213  EIGEN_DEVICE_FUNC const internal::remove_all_t<XprTypeNested>& nestedExpression() const { return m_xpr; }
214 
215  EIGEN_DEVICE_FUNC XprType& nestedExpression() { return m_xpr; }
216 
218  EIGEN_DEVICE_FUNC constexpr Index innerStride() const { return m_xpr.innerStride(); }
219 
221  EIGEN_DEVICE_FUNC constexpr Index outerStride() const {
222  return (((Flags & RowMajorBit) == RowMajorBit) ? this->cols() : this->rows()) * m_xpr.innerStride();
223  }
224 
225  protected:
226  XprTypeNested m_xpr;
227 };
228 
229 // Evaluators
230 template <typename ArgType, int Rows, int Cols, int Order, bool HasDirectAccess>
231 struct reshaped_evaluator;
232 
233 template <typename ArgType, int Rows, int Cols, int Order>
234 struct evaluator<Reshaped<ArgType, Rows, Cols, Order> >
235  : reshaped_evaluator<ArgType, Rows, Cols, Order, traits<Reshaped<ArgType, Rows, Cols, Order> >::HasDirectAccess> {
236  typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
237  typedef typename XprType::Scalar Scalar;
238  // TODO: should check for smaller packet types
239  typedef typename packet_traits<Scalar>::type PacketScalar;
240 
241  enum {
242  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
243  HasDirectAccess = traits<XprType>::HasDirectAccess,
244 
245  // RowsAtCompileTime = traits<XprType>::RowsAtCompileTime,
246  // ColsAtCompileTime = traits<XprType>::ColsAtCompileTime,
247  // MaxRowsAtCompileTime = traits<XprType>::MaxRowsAtCompileTime,
248  // MaxColsAtCompileTime = traits<XprType>::MaxColsAtCompileTime,
249  //
250  // InnerStrideAtCompileTime = traits<XprType>::HasSameStorageOrderAsXprType
251  // ? int(inner_stride_at_compile_time<ArgType>::ret)
252  // : Dynamic,
253  // OuterStrideAtCompileTime = Dynamic,
254 
255  FlagsLinearAccessBit =
256  (traits<XprType>::RowsAtCompileTime == 1 || traits<XprType>::ColsAtCompileTime == 1 || HasDirectAccess)
258  : 0,
259  FlagsRowMajorBit = (traits<XprType>::ReshapedStorageOrder == int(RowMajor)) ? RowMajorBit : 0,
260  FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0,
261  Flags0 = evaluator<ArgType>::Flags & (HereditaryBits & ~RowMajorBit),
262  Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit | FlagsDirectAccessBit,
263 
264  PacketAlignment = unpacket_traits<PacketScalar>::alignment,
265  Alignment = evaluator<ArgType>::Alignment
266  };
267  typedef reshaped_evaluator<ArgType, Rows, Cols, Order, HasDirectAccess> reshaped_evaluator_type;
268  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : reshaped_evaluator_type(xpr) {
269  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
270  }
271 };
272 
273 template <typename ArgType, int Rows, int Cols, int Order>
274 struct reshaped_evaluator<ArgType, Rows, Cols, Order, /* HasDirectAccess */ false>
275  : evaluator_base<Reshaped<ArgType, Rows, Cols, Order> > {
276  typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
277 
278  enum {
279  CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of index computations */,
280 
281  Flags = (evaluator<ArgType>::Flags & (HereditaryBits /*| LinearAccessBit | DirectAccessBit*/)),
282 
283  Alignment = 0
284  };
285 
286  EIGEN_DEVICE_FUNC explicit reshaped_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_xpr(xpr) {
287  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
288  }
289 
290  typedef typename XprType::Scalar Scalar;
291  typedef typename XprType::CoeffReturnType CoeffReturnType;
292 
293  typedef std::pair<Index, Index> RowCol;
294 
295  EIGEN_DEVICE_FUNC inline RowCol index_remap(Index rowId, Index colId) const {
296  if (Order == ColMajor) {
297  const Index nth_elem_idx = colId * m_xpr.rows() + rowId;
298  return RowCol(nth_elem_idx % m_xpr.nestedExpression().rows(), nth_elem_idx / m_xpr.nestedExpression().rows());
299  } else {
300  const Index nth_elem_idx = colId + rowId * m_xpr.cols();
301  return RowCol(nth_elem_idx / m_xpr.nestedExpression().cols(), nth_elem_idx % m_xpr.nestedExpression().cols());
302  }
303  }
304 
305  EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index rowId, Index colId) {
306  EIGEN_STATIC_ASSERT_LVALUE(XprType)
307  const RowCol row_col = index_remap(rowId, colId);
308  return m_argImpl.coeffRef(row_col.first, row_col.second);
309  }
310 
311  EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index rowId, Index colId) const {
312  const RowCol row_col = index_remap(rowId, colId);
313  return m_argImpl.coeffRef(row_col.first, row_col.second);
314  }
315 
316  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const {
317  const RowCol row_col = index_remap(rowId, colId);
318  return m_argImpl.coeff(row_col.first, row_col.second);
319  }
320 
321  EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index) {
322  EIGEN_STATIC_ASSERT_LVALUE(XprType)
323  const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0);
324  return m_argImpl.coeffRef(row_col.first, row_col.second);
325  }
326 
327  EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const {
328  const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0);
329  return m_argImpl.coeffRef(row_col.first, row_col.second);
330  }
331 
332  EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index index) const {
333  const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0);
334  return m_argImpl.coeff(row_col.first, row_col.second);
335  }
336 #if 0
337  EIGEN_DEVICE_FUNC
338  template<int LoadMode>
339  inline PacketScalar packet(Index rowId, Index colId) const
340  {
341  const RowCol row_col = index_remap(rowId, colId);
342  return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second);
343 
344  }
345 
346  template<int LoadMode>
347  EIGEN_DEVICE_FUNC
348  inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
349  {
350  const RowCol row_col = index_remap(rowId, colId);
351  m_argImpl.const_cast_derived().template writePacket<Unaligned>
352  (row_col.first, row_col.second, val);
353  }
354 
355  template<int LoadMode>
356  EIGEN_DEVICE_FUNC
357  inline PacketScalar packet(Index index) const
358  {
359  const RowCol row_col = index_remap(RowsAtCompileTime == 1 ? 0 : index,
360  RowsAtCompileTime == 1 ? index : 0);
361  return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second);
362  }
363 
364  template<int LoadMode>
365  EIGEN_DEVICE_FUNC
366  inline void writePacket(Index index, const PacketScalar& val)
367  {
368  const RowCol row_col = index_remap(RowsAtCompileTime == 1 ? 0 : index,
369  RowsAtCompileTime == 1 ? index : 0);
370  return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second, val);
371  }
372 #endif
373  protected:
374  evaluator<ArgType> m_argImpl;
375  const XprType& m_xpr;
376 };
377 
378 template <typename ArgType, int Rows, int Cols, int Order>
379 struct reshaped_evaluator<ArgType, Rows, Cols, Order, /* HasDirectAccess */ true>
380  : mapbase_evaluator<Reshaped<ArgType, Rows, Cols, Order>,
381  typename Reshaped<ArgType, Rows, Cols, Order>::PlainObject> {
382  typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
383  typedef typename XprType::Scalar Scalar;
384 
385  EIGEN_DEVICE_FUNC explicit reshaped_evaluator(const XprType& xpr)
386  : mapbase_evaluator<XprType, typename XprType::PlainObject>(xpr) {
387  // TODO: for the 3.4 release, this should be turned to an internal assertion, but let's keep it as is for the beta
388  // lifetime
389  eigen_assert(((std::uintptr_t(xpr.data()) % plain_enum_max(1, evaluator<XprType>::Alignment)) == 0) &&
390  "data is not aligned");
391  }
392 };
393 
394 } // end namespace internal
395 
396 } // end namespace Eigen
397 
398 #endif // EIGEN_RESHAPED_H
Reshaped(XprType &xpr, Index reshapeRows, Index reshapeCols)
Definition: Reshaped.h:118
Definition: Constants.h:318
const unsigned int DirectAccessBit
Definition: Constants.h:159
const unsigned int LvalueBit
Definition: Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
const unsigned int RowMajorBit
Definition: Constants.h:70
const unsigned int PacketAccessBit
Definition: Constants.h:97
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Definition: Constants.h:320
Expression of a fixed-size or dynamic-size reshape.
Definition: Reshaped.h:99
const int Dynamic
Definition: Constants.h:25
const unsigned int LinearAccessBit
Definition: Constants.h:133