TensorRef.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) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
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_CXX11_TENSOR_TENSOR_REF_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_REF_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 namespace Eigen {
16 
17 namespace internal {
18 
19 template <typename Dimensions, typename Scalar>
20 class TensorLazyBaseEvaluator {
21  public:
22  TensorLazyBaseEvaluator() : m_refcount(0) { }
23  virtual ~TensorLazyBaseEvaluator() { }
24 
25  EIGEN_DEVICE_FUNC virtual const Dimensions& dimensions() const = 0;
26  EIGEN_DEVICE_FUNC virtual const Scalar* data() const = 0;
27 
28  EIGEN_DEVICE_FUNC virtual const Scalar coeff(DenseIndex index) const = 0;
29  EIGEN_DEVICE_FUNC virtual Scalar& coeffRef(DenseIndex index) = 0;
30 
31  void incrRefCount() { ++m_refcount; }
32  void decrRefCount() { --m_refcount; }
33  int refCount() const { return m_refcount; }
34 
35  private:
36  // No copy, no assignment;
37  TensorLazyBaseEvaluator(const TensorLazyBaseEvaluator& other);
38  TensorLazyBaseEvaluator& operator = (const TensorLazyBaseEvaluator& other);
39 
40  int m_refcount;
41 };
42 
43 
44 template <typename Dimensions, typename Expr, typename Device>
45 class TensorLazyEvaluatorReadOnly : public TensorLazyBaseEvaluator<Dimensions, typename TensorEvaluator<Expr, Device>::Scalar> {
46  public:
47  // typedef typename TensorEvaluator<Expr, Device>::Dimensions Dimensions;
48  typedef typename TensorEvaluator<Expr, Device>::Scalar Scalar;
49  typedef StorageMemory<Scalar, Device> Storage;
50  typedef typename Storage::Type EvaluatorPointerType;
51  typedef TensorEvaluator<Expr, Device> EvalType;
52 
53  TensorLazyEvaluatorReadOnly(const Expr& expr, const Device& device) : m_impl(expr, device), m_dummy(Scalar(0)) {
54  m_dims = m_impl.dimensions();
55  m_impl.evalSubExprsIfNeeded(NULL);
56  }
57  virtual ~TensorLazyEvaluatorReadOnly() {
58  m_impl.cleanup();
59  }
60 
61  EIGEN_DEVICE_FUNC virtual const Dimensions& dimensions() const {
62  return m_dims;
63  }
64  EIGEN_DEVICE_FUNC virtual const Scalar* data() const {
65  return m_impl.data();
66  }
67 
68  EIGEN_DEVICE_FUNC virtual const Scalar coeff(DenseIndex index) const {
69  return m_impl.coeff(index);
70  }
71  EIGEN_DEVICE_FUNC virtual Scalar& coeffRef(DenseIndex /*index*/) {
72  eigen_assert(false && "can't reference the coefficient of a rvalue");
73  return m_dummy;
74  };
75 
76  protected:
77  TensorEvaluator<Expr, Device> m_impl;
78  Dimensions m_dims;
79  Scalar m_dummy;
80 };
81 
82 template <typename Dimensions, typename Expr, typename Device>
83 class TensorLazyEvaluatorWritable : public TensorLazyEvaluatorReadOnly<Dimensions, Expr, Device> {
84  public:
85  typedef TensorLazyEvaluatorReadOnly<Dimensions, Expr, Device> Base;
86  typedef typename Base::Scalar Scalar;
87  typedef StorageMemory<Scalar, Device> Storage;
88  typedef typename Storage::Type EvaluatorPointerType;
89 
90  TensorLazyEvaluatorWritable(const Expr& expr, const Device& device) : Base(expr, device) {
91  }
92  virtual ~TensorLazyEvaluatorWritable() {
93  }
94 
95  EIGEN_DEVICE_FUNC virtual Scalar& coeffRef(DenseIndex index) {
96  return this->m_impl.coeffRef(index);
97  }
98 };
99 
100 template <typename Dimensions, typename Expr, typename Device>
101 class TensorLazyEvaluator : public std::conditional_t<bool(internal::is_lvalue<Expr>::value),
102  TensorLazyEvaluatorWritable<Dimensions, Expr, Device>,
103  TensorLazyEvaluatorReadOnly<Dimensions, const Expr, Device> > {
104  public:
105  typedef std::conditional_t<bool(internal::is_lvalue<Expr>::value),
106  TensorLazyEvaluatorWritable<Dimensions, Expr, Device>,
107  TensorLazyEvaluatorReadOnly<Dimensions, const Expr, Device> > Base;
108  typedef typename Base::Scalar Scalar;
109 
110  TensorLazyEvaluator(const Expr& expr, const Device& device) : Base(expr, device) {
111  }
112  virtual ~TensorLazyEvaluator() {
113  }
114 };
115 
116 } // namespace internal
117 
118 
126 template<typename PlainObjectType> class TensorRef : public TensorBase<TensorRef<PlainObjectType> >
127 {
128  public:
130  typedef typename PlainObjectType::Base Base;
131  typedef typename Eigen::internal::nested<Self>::type Nested;
132  typedef typename internal::traits<PlainObjectType>::StorageKind StorageKind;
133  typedef typename internal::traits<PlainObjectType>::Index Index;
134  typedef typename internal::traits<PlainObjectType>::Scalar Scalar;
136  typedef typename Base::CoeffReturnType CoeffReturnType;
137  typedef Scalar* PointerType;
139 
140  static constexpr Index NumIndices = PlainObjectType::NumIndices;
141  typedef typename PlainObjectType::Dimensions Dimensions;
142 
143  static constexpr int Layout = PlainObjectType::Layout;
144  enum {
145  IsAligned = false,
146  PacketAccess = false,
147  BlockAccess = false,
149  CoordAccess = false, // to be implemented
150  RawAccess = false
151  };
152 
153  //===- Tensor block evaluation strategy (see TensorBlock.h) -----------===//
154  typedef internal::TensorBlockNotImplemented TensorBlock;
155  //===------------------------------------------------------------------===//
156 
157  EIGEN_STRONG_INLINE TensorRef() : m_evaluator(NULL) {
158  }
159 
160  template <typename Expression>
161  EIGEN_STRONG_INLINE TensorRef(const Expression& expr) : m_evaluator(new internal::TensorLazyEvaluator<Dimensions, Expression, DefaultDevice>(expr, DefaultDevice())) {
162  m_evaluator->incrRefCount();
163  }
164 
165  template <typename Expression>
166  EIGEN_STRONG_INLINE TensorRef& operator = (const Expression& expr) {
167  unrefEvaluator();
168  m_evaluator = new internal::TensorLazyEvaluator<Dimensions, Expression, DefaultDevice>(expr, DefaultDevice());
169  m_evaluator->incrRefCount();
170  return *this;
171  }
172 
174  unrefEvaluator();
175  }
176 
177  TensorRef(const TensorRef& other) : TensorBase<TensorRef<PlainObjectType> >(other), m_evaluator(other.m_evaluator) {
178  eigen_assert(m_evaluator->refCount() > 0);
179  m_evaluator->incrRefCount();
180  }
181 
182  TensorRef& operator = (const TensorRef& other) {
183  if (this != &other) {
184  unrefEvaluator();
185  m_evaluator = other.m_evaluator;
186  eigen_assert(m_evaluator->refCount() > 0);
187  m_evaluator->incrRefCount();
188  }
189  return *this;
190  }
191 
193  EIGEN_STRONG_INLINE Index rank() const { return m_evaluator->dimensions().size(); }
195  EIGEN_STRONG_INLINE Index dimension(Index n) const { return m_evaluator->dimensions()[n]; }
197  EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_evaluator->dimensions(); }
199  EIGEN_STRONG_INLINE Index size() const { return m_evaluator->dimensions().TotalSize(); }
201  EIGEN_STRONG_INLINE const Scalar* data() const { return m_evaluator->data(); }
202 
204  EIGEN_STRONG_INLINE const Scalar operator()(Index index) const
205  {
206  return m_evaluator->coeff(index);
207  }
208 
209  template<typename... IndexTypes> EIGEN_DEVICE_FUNC
210  EIGEN_STRONG_INLINE const Scalar operator()(Index firstIndex, IndexTypes... otherIndices) const
211  {
212  const std::size_t num_indices = (sizeof...(otherIndices) + 1);
213  const array<Index, num_indices> indices{{firstIndex, otherIndices...}};
214  return coeff(indices);
215  }
216  template<typename... IndexTypes> EIGEN_DEVICE_FUNC
217  EIGEN_STRONG_INLINE Scalar& coeffRef(Index firstIndex, IndexTypes... otherIndices)
218  {
219  const std::size_t num_indices = (sizeof...(otherIndices) + 1);
220  const array<Index, num_indices> indices{{firstIndex, otherIndices...}};
221  return coeffRef(indices);
222  }
223 
224  template <std::size_t NumIndices> EIGEN_DEVICE_FUNC
225  EIGEN_STRONG_INLINE const Scalar coeff(const array<Index, NumIndices>& indices) const
226  {
227  const Dimensions& dims = this->dimensions();
228  Index index = 0;
229  if (PlainObjectType::Options & RowMajor) {
230  index += indices[0];
231  for (size_t i = 1; i < NumIndices; ++i) {
232  index = index * dims[i] + indices[i];
233  }
234  } else {
235  index += indices[NumIndices-1];
236  for (int i = NumIndices-2; i >= 0; --i) {
237  index = index * dims[i] + indices[i];
238  }
239  }
240  return m_evaluator->coeff(index);
241  }
242  template <std::size_t NumIndices> EIGEN_DEVICE_FUNC
243  EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices)
244  {
245  const Dimensions& dims = this->dimensions();
246  Index index = 0;
247  if (PlainObjectType::Options & RowMajor) {
248  index += indices[0];
249  for (size_t i = 1; i < NumIndices; ++i) {
250  index = index * dims[i] + indices[i];
251  }
252  } else {
253  index += indices[NumIndices-1];
254  for (int i = NumIndices-2; i >= 0; --i) {
255  index = index * dims[i] + indices[i];
256  }
257  }
258  return m_evaluator->coeffRef(index);
259  }
260 
262  EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
263  {
264  return m_evaluator->coeff(index);
265  }
266 
268  EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
269  {
270  return m_evaluator->coeffRef(index);
271  }
272 
273  private:
274  EIGEN_STRONG_INLINE void unrefEvaluator() {
275  if (m_evaluator) {
276  m_evaluator->decrRefCount();
277  if (m_evaluator->refCount() == 0) {
278  delete m_evaluator;
279  }
280  }
281  }
282 
283  internal::TensorLazyBaseEvaluator<Dimensions, Scalar>* m_evaluator;
284 };
285 
286 
287 // evaluator for rvalues
288 template<typename Derived, typename Device>
289 struct TensorEvaluator<const TensorRef<Derived>, Device>
290 {
291  typedef typename Derived::Index Index;
292  typedef typename Derived::Scalar Scalar;
293  typedef typename Derived::Scalar CoeffReturnType;
295  typedef typename Derived::Dimensions Dimensions;
298 
299  static constexpr int Layout = TensorRef<Derived>::Layout;
300  enum {
301  IsAligned = false,
302  PacketAccess = false,
303  BlockAccess = false,
304  PreferBlockAccess = false,
305  CoordAccess = false, // to be implemented
306  RawAccess = false
307  };
308 
309  //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
310  typedef internal::TensorBlockNotImplemented TensorBlock;
311  //===--------------------------------------------------------------------===//
312 
313  EIGEN_STRONG_INLINE TensorEvaluator(const TensorRef<Derived>& m, const Device&)
314  : m_ref(m)
315  { }
316 
317  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_ref.dimensions(); }
318 
319  EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType) {
320  return true;
321  }
322 
323  EIGEN_STRONG_INLINE void cleanup() { }
324 
325  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const {
326  return m_ref.coeff(index);
327  }
328 
329  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
330  return m_ref.coeffRef(index);
331  }
332 
333  EIGEN_DEVICE_FUNC const Scalar* data() const { return m_ref.data(); }
334 
335  protected:
337 };
338 
339 
340 // evaluator for lvalues
341 template<typename Derived, typename Device>
342 struct TensorEvaluator<TensorRef<Derived>, Device> : public TensorEvaluator<const TensorRef<Derived>, Device>
343 {
344  typedef typename Derived::Index Index;
345  typedef typename Derived::Scalar Scalar;
346  typedef typename Derived::Scalar CoeffReturnType;
348  typedef typename Derived::Dimensions Dimensions;
349 
351 
352  enum {
353  IsAligned = false,
354  PacketAccess = false,
355  BlockAccess = false,
356  PreferBlockAccess = false,
357  RawAccess = false
358  };
359 
360  //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
361  typedef internal::TensorBlockNotImplemented TensorBlock;
362  //===--------------------------------------------------------------------===//
363 
364  EIGEN_STRONG_INLINE TensorEvaluator(TensorRef<Derived>& m, const Device& d) : Base(m, d)
365  { }
366 
367  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
368  return this->m_ref.coeffRef(index);
369  }
370 };
371 
372 
373 
374 } // end namespace Eigen
375 
376 #endif // EIGEN_CXX11_TENSOR_TENSOR_REF_H
Matrix3f m
int n
int i
#define EIGEN_DEVICE_FUNC
#define eigen_assert(x)
int data[]
The tensor base class.
A reference to a tensor expression The expression will be evaluated lazily (as much as possible).
Definition: TensorRef.h:127
internal::traits< PlainObjectType >::Index Index
Definition: TensorRef.h:133
TensorRef(const TensorRef &other)
Definition: TensorRef.h:177
const Scalar coeff(const array< Index, NumIndices > &indices) const
Definition: TensorRef.h:225
PlainObjectType::Dimensions Dimensions
Definition: TensorRef.h:141
Scalar & coeffRef(Index index)
Definition: TensorRef.h:268
Index size() const
Definition: TensorRef.h:199
internal::TensorLazyBaseEvaluator< Dimensions, Scalar > * m_evaluator
Definition: TensorRef.h:283
void unrefEvaluator()
Definition: TensorRef.h:274
Base::CoeffReturnType CoeffReturnType
Definition: TensorRef.h:136
NumTraits< Scalar >::Real RealScalar
Definition: TensorRef.h:135
static constexpr Index NumIndices
Definition: TensorRef.h:140
TensorRef(const Expression &expr)
Definition: TensorRef.h:161
Index dimension(Index n) const
Definition: TensorRef.h:195
PlainObjectType::Base Base
Definition: TensorRef.h:130
Scalar & coeffRef(Index firstIndex, IndexTypes... otherIndices)
Definition: TensorRef.h:217
PointerType PointerArgType
Definition: TensorRef.h:138
const Scalar * data() const
Definition: TensorRef.h:201
TensorRef< PlainObjectType > Self
Definition: TensorRef.h:129
Scalar & coeffRef(const array< Index, NumIndices > &indices)
Definition: TensorRef.h:243
Eigen::internal::nested< Self >::type Nested
Definition: TensorRef.h:131
internal::TensorBlockNotImplemented TensorBlock
Definition: TensorRef.h:154
const Scalar coeff(Index index) const
Definition: TensorRef.h:262
const Scalar operator()(Index index) const
Definition: TensorRef.h:204
Index rank() const
Definition: TensorRef.h:193
const Dimensions & dimensions() const
Definition: TensorRef.h:197
internal::traits< PlainObjectType >::StorageKind StorageKind
Definition: TensorRef.h:132
internal::traits< PlainObjectType >::Scalar Scalar
Definition: TensorRef.h:134
static constexpr int Layout
Definition: TensorRef.h:143
const Scalar operator()(Index firstIndex, IndexTypes... otherIndices) const
Definition: TensorRef.h:210
TensorRef & operator=(const Expression &expr)
Definition: TensorRef.h:166
Scalar * PointerType
Definition: TensorRef.h:137
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
std::array< T, N > array
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
internal::packet_traits< Scalar >::type type
Definition: TensorMeta.h:55
internal::TensorBlockNotImplemented TensorBlock
Definition: TensorRef.h:361
PacketType< CoeffReturnType, Device >::type PacketReturnType
Definition: TensorRef.h:347
TensorEvaluator< const TensorRef< Derived >, Device > Base
Definition: TensorRef.h:350
TensorEvaluator(TensorRef< Derived > &m, const Device &d)
Definition: TensorRef.h:364
TensorEvaluator(const TensorRef< Derived > &m, const Device &)
Definition: TensorRef.h:313
PacketType< CoeffReturnType, Device >::type PacketReturnType
Definition: TensorRef.h:294
internal::TensorBlockNotImplemented TensorBlock
Definition: TensorRef.h:310
StorageMemory< CoeffReturnType, Device > Storage
Definition: TensorRef.h:296
A cost model used to limit the number of threads used for evaluating tensor expression.
static constexpr int Layout
Derived::Scalar Scalar