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