Eigen-unsupported  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
Tensor.h
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// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
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_CXX11_TENSOR_TENSOR_H
12#define EIGEN_CXX11_TENSOR_TENSOR_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
66
67template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
68class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexType_> > {
69 public:
70 typedef Tensor<Scalar_, NumIndices_, Options_, IndexType_> Self;
72 typedef typename Eigen::internal::nested<Self>::type Nested;
73 typedef typename internal::traits<Self>::StorageKind StorageKind;
74 typedef typename internal::traits<Self>::Index Index;
75 typedef Scalar_ Scalar;
76 typedef typename NumTraits<Scalar>::Real RealScalar;
77 typedef typename Base::CoeffReturnType CoeffReturnType;
78
79 enum { IsAligned = (EIGEN_MAX_ALIGN_BYTES > 0) && !(Options_ & DontAlign), CoordAccess = true, RawAccess = true };
80
81 static constexpr int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
82 static constexpr int Options = Options_;
83 static constexpr int NumIndices = NumIndices_;
84 typedef DSizes<Index, NumIndices_> Dimensions;
85
86 protected:
87 TensorStorage<Scalar, Dimensions, Options> m_storage;
88
89 template <typename CustomIndices>
90 struct isOfNormalIndex {
91 static const bool is_array = internal::is_base_of<array<Index, NumIndices>, CustomIndices>::value;
92 static const bool is_int = NumTraits<CustomIndices>::IsInteger;
93 static const bool value = is_array | is_int;
94 };
95
96 public:
97 // Metadata
98 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rank() const { return NumIndices; }
99 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index dimension(std::size_t n) const { return m_storage.dimensions()[n]; }
100 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_storage.dimensions(); }
101 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return m_storage.size(); }
102 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar* data() { return m_storage.data(); }
103 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar* data() const { return m_storage.data(); }
104
105 // This makes EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
106 // work, because that uses base().coeffRef() - and we don't yet
107 // implement a similar class hierarchy
108 inline Self& base() { return *this; }
109 inline const Self& base() const { return *this; }
110
111 template <typename... IndexTypes>
112 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index firstIndex, Index secondIndex,
113 IndexTypes... otherIndices) const {
114 // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
115 EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 2 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
116 return coeff(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}});
117 }
118
119 // normal indices
120 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(const array<Index, NumIndices>& indices) const {
121 eigen_internal_assert(checkIndexRange(indices));
122 return m_storage.data()[linearizedIndex(indices)];
123 }
124
125 // custom indices
126 template <typename CustomIndices, EIGEN_SFINAE_ENABLE_IF(!(isOfNormalIndex<CustomIndices>::value))>
127 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(CustomIndices& indices) const {
128 return coeff(internal::customIndices2Array<Index, NumIndices>(indices));
129 }
130
131 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff() const {
132 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
133 return m_storage.data()[0];
134 }
135
136 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const {
137 eigen_internal_assert(index >= 0 && index < size());
138 return m_storage.data()[index];
139 }
140
141 template <typename... IndexTypes>
142 inline Scalar& coeffRef(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) {
143 // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
144 EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 2 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
145 return coeffRef(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}});
146 }
147
148 // normal indices
149 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices) {
150 eigen_internal_assert(checkIndexRange(indices));
151 return m_storage.data()[linearizedIndex(indices)];
152 }
153
154 // custom indices
155 template <typename CustomIndices, EIGEN_SFINAE_ENABLE_IF(!(isOfNormalIndex<CustomIndices>::value))>
156 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(CustomIndices& indices) {
157 return coeffRef(internal::customIndices2Array<Index, NumIndices>(indices));
158 }
159
160 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef() {
161 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
162 return m_storage.data()[0];
163 }
164
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
166 eigen_internal_assert(index >= 0 && index < size());
167 return m_storage.data()[index];
168 }
169
170 template <typename... IndexTypes>
171 inline const Scalar& operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) const {
172 // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
173 EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 2 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
174 return this->operator()(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}});
175 }
176
177 // custom indices
178 template <typename CustomIndices, EIGEN_SFINAE_ENABLE_IF(!(isOfNormalIndex<CustomIndices>::value))>
179 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(CustomIndices& indices) const {
180 return coeff(internal::customIndices2Array<Index, NumIndices>(indices));
181 }
182
183 // normal indices
184 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const {
185 return coeff(indices);
186 }
187
188 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(Index index) const {
189 eigen_internal_assert(index >= 0 && index < size());
190 return coeff(index);
191 }
192
193 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()() const {
194 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
195 return coeff();
196 }
197
198 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator[](Index index) const {
199 // The bracket operator is only for vectors, use the parenthesis operator instead.
200 EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
201 return coeff(index);
202 }
203
204 template <typename... IndexTypes>
205 inline Scalar& operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) {
206 // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
207 EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 2 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
208 return operator()(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}});
209 }
210
211 // normal indices
212 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices) {
213 return coeffRef(indices);
214 }
215
216 // custom indices
217 template <typename CustomIndices, EIGEN_SFINAE_ENABLE_IF(!(isOfNormalIndex<CustomIndices>::value))>
218 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(CustomIndices& indices) {
219 return coeffRef(internal::customIndices2Array<Index, NumIndices>(indices));
220 }
221
222 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index index) {
223 eigen_assert(index >= 0 && index < size());
224 return coeffRef(index);
225 }
226
227 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()() {
228 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
229 return coeffRef();
230 }
231
232 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator[](Index index) {
233 // The bracket operator is only for vectors, use the parenthesis operator instead
234 EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE)
235 return coeffRef(index);
236 }
237
238 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor() : m_storage() {}
239
240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(const Self& other) : Base(other), m_storage(other.m_storage) {}
241
242 template <typename... IndexTypes>
243 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(Index firstDimension, IndexTypes... otherDimensions)
244 : m_storage(firstDimension, otherDimensions...) {
245 // The number of dimensions used to construct a tensor must be equal to the rank of the tensor.
246 EIGEN_STATIC_ASSERT(sizeof...(otherDimensions) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
247 }
248
250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit Tensor(const array<Index, NumIndices>& dimensions)
251 : m_storage(internal::array_prod(dimensions), dimensions) {
252 EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
253 }
254
255 template <typename OtherDerived>
256 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(const TensorBase<OtherDerived, ReadOnlyAccessors>& other) {
257 EIGEN_STATIC_ASSERT(OtherDerived::NumDimensions == Base::NumDimensions, Number_of_dimensions_must_match)
259 Assign assign(*this, other.derived());
260 resize(TensorEvaluator<const Assign, DefaultDevice>(assign, DefaultDevice()).dimensions());
261 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
262 }
263
264 template <typename OtherDerived>
265 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(const TensorBase<OtherDerived, WriteAccessors>& other) {
266 EIGEN_STATIC_ASSERT(OtherDerived::NumDimensions == Base::NumDimensions, Number_of_dimensions_must_match)
267 typedef TensorAssignOp<Tensor, const OtherDerived> Assign;
268 Assign assign(*this, other.derived());
269 resize(TensorEvaluator<const Assign, DefaultDevice>(assign, DefaultDevice()).dimensions());
270 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
271 }
272
273 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(Self&& other) : m_storage(std::move(other.m_storage)) {}
274 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor& operator=(Self&& other) {
275 m_storage = std::move(other.m_storage);
276 return *this;
277 }
278
279 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor& operator=(const Tensor& other) {
280 typedef TensorAssignOp<Tensor, const Tensor> Assign;
281 Assign assign(*this, other);
282 resize(TensorEvaluator<const Assign, DefaultDevice>(assign, DefaultDevice()).dimensions());
283 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
284 return *this;
285 }
286 template <typename OtherDerived>
287 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor& operator=(const OtherDerived& other) {
288 typedef TensorAssignOp<Tensor, const OtherDerived> Assign;
289 Assign assign(*this, other);
290 resize(TensorEvaluator<const Assign, DefaultDevice>(assign, DefaultDevice()).dimensions());
291 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
292 return *this;
293 }
294
295 template <typename... IndexTypes>
296 EIGEN_DEVICE_FUNC void resize(Index firstDimension, IndexTypes... otherDimensions) {
297 // The number of dimensions used to resize a tensor must be equal to the rank of the tensor.
298 EIGEN_STATIC_ASSERT(sizeof...(otherDimensions) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
299 resize(array<Index, NumIndices>{{firstDimension, otherDimensions...}});
300 }
301
303 EIGEN_DEVICE_FUNC void resize(const array<Index, NumIndices>& dimensions) {
304#ifndef EIGEN_NO_DEBUG
305 Index size = Index(1);
306 for (int i = 0; i < NumIndices; i++) {
307 internal::check_rows_cols_for_overflow<Dynamic, Dynamic, Dynamic>::run(size, dimensions[i]);
308 size *= dimensions[i];
309 }
310#else
311 Index size = internal::array_prod(dimensions);
312#endif
313
314#ifdef EIGEN_INITIALIZE_COEFFS
315 bool size_changed = size != this->size();
316 m_storage.resize(size, dimensions);
317 if (size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
318#else
319 m_storage.resize(size, dimensions);
320#endif
321 }
322
323 EIGEN_DEVICE_FUNC void resize() {
324 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
325 // Nothing to do: rank 0 tensors have fixed size
326 }
327
328 template <typename FirstType, typename... OtherTypes>
329 EIGEN_DEVICE_FUNC void resize(const Eigen::IndexList<FirstType, OtherTypes...>& dimensions) {
330 array<Index, NumIndices> dims;
331 for (int i = 0; i < NumIndices; ++i) {
332 dims[i] = static_cast<Index>(dimensions[i]);
333 }
334 resize(dims);
335 }
336
338 template <typename CustomDimension, EIGEN_SFINAE_ENABLE_IF(!(isOfNormalIndex<CustomDimension>::value))>
339 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(CustomDimension& dimensions) {
340 resize(internal::customIndices2Array<Index, NumIndices>(dimensions));
341 }
342
343 template <typename std::ptrdiff_t... Indices>
344 EIGEN_DEVICE_FUNC void resize(const Sizes<Indices...>& dimensions) {
345 array<Index, NumIndices> dims;
346 for (int i = 0; i < NumIndices; ++i) {
347 dims[i] = static_cast<Index>(dimensions[i]);
348 }
349 resize(dims);
350 }
351
352#ifdef EIGEN_TENSOR_PLUGIN
353#include EIGEN_TENSOR_PLUGIN
354#endif
355
356 protected:
357 bool checkIndexRange(const array<Index, NumIndices>& indices) const {
358 using internal::array_apply_and_reduce;
359 using internal::array_zip_and_reduce;
360 using internal::greater_equal_zero_op;
361 using internal::lesser_op;
362 using internal::logical_and_op;
363
364 return
365 // check whether the indices are all >= 0
366 array_apply_and_reduce<logical_and_op, greater_equal_zero_op>(indices) &&
367 // check whether the indices fit in the dimensions
368 array_zip_and_reduce<logical_and_op, lesser_op>(indices, m_storage.dimensions());
369 }
370
371 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index linearizedIndex(const array<Index, NumIndices>& indices) const {
372 if (Options & RowMajor) {
373 return m_storage.dimensions().IndexOfRowMajor(indices);
374 } else {
375 return m_storage.dimensions().IndexOfColMajor(indices);
376 }
377 }
378};
379
380} // end namespace Eigen
381
382#endif // EIGEN_CXX11_TENSOR_TENSOR_H
Definition TensorAssign.h:55
The tensor base class.
Definition TensorForwardDeclarations.h:68
The tensor class.
Definition Tensor.h:68
Tensor(const array< Index, NumIndices > &dimensions)
Definition Tensor.h:250
void resize(CustomDimension &dimensions)
Definition Tensor.h:339
void resize(const array< Index, NumIndices > &dimensions)
Definition Tensor.h:303
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The tensor evaluator class.
Definition TensorEvaluator.h:30