blob: 9dc95916c0cd4da5d10e7f9a298a35a906721f1b [file] [log] [blame]
Christian Seilerf97b3cd2013-11-14 22:52:37 +01001// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
Benoit Steinerae697b42014-10-16 14:52:50 -07004// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
Christian Seilerf6bac192013-11-16 00:03:23 +01005// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
Christian Seilerf97b3cd2013-11-14 22:52:37 +01006//
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
Antonio Sánchez6e4d5d42023-08-21 16:25:22 +000014// IWYU pragma: private
Rasmus Munk Larsend7d0bf82021-09-10 19:12:26 +000015#include "./InternalHeaderCheck.h"
16
Christian Seilerf97b3cd2013-11-14 22:52:37 +010017namespace Eigen {
18
19/** \class Tensor
Tobias Woodf38e16c2023-11-29 11:12:48 +000020 * \ingroup CXX11_Tensor_Module
21 *
22 * \brief The tensor class.
23 *
24 * The %Tensor class is the work-horse for all \em dense tensors within Eigen.
25 *
26 * The %Tensor class encompasses only dynamic-size objects so far.
27 *
28 * The first two template parameters are required:
29 * \tparam Scalar_ Numeric type, e.g. float, double, int or `std::complex<float>`.
30 * User defined scalar types are supported as well (see \ref user_defined_scalars "here").
31 * \tparam NumIndices_ Number of indices (i.e. rank of the tensor)
32 *
33 * The remaining template parameters are optional -- in most cases you don't have to worry about them.
34 * \tparam Options_ A combination of either \b #RowMajor or \b #ColMajor, and of either
35 * \b #AutoAlign or \b #DontAlign.
36 * The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter
37 * controls alignment, which is required for vectorization. It defaults to aligning tensors. Note that tensors currently
38 * do not support any operations that profit from vectorization. Support for such operations (i.e. adding two tensors
39 * etc.) is planned.
40 *
41 * You can access elements of tensors using normal subscripting:
42 *
43 * \code
44 * Eigen::Tensor<double, 4> t(10, 10, 10, 10);
45 * t(0, 1, 2, 3) = 42.0;
46 * \endcode
47 *
48 * This class can be extended with the help of the plugin mechanism described on the page
49 * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_TENSOR_PLUGIN,
50 * \c EIGEN_TENSORBASE_PLUGIN, and \c EIGEN_READONLY_TENSORBASE_PLUGIN.
51 *
52 * <i><b>Some notes:</b></i>
53 *
54 * <dl>
55 * <dt><b>Relation to other parts of Eigen:</b></dt>
56 * <dd>The midterm development goal for this class is to have a similar hierarchy as Eigen uses for matrices, so that
57 * taking blocks or using tensors in expressions is easily possible, including an interface with the vector/matrix code
58 * by providing .asMatrix() and .asVector() (or similar) methods for rank 2 and 1 tensors. However, currently, the
59 * %Tensor class does not provide any of these features and is only available as a stand-alone class that just allows
60 * for coefficient access. Also, when fixed-size tensors are implemented, the number of template arguments is likely to
61 * change dramatically.</dd>
62 * </dl>
63 *
64 * \ref TopicStorageOrders
65 */
Christian Seilerf97b3cd2013-11-14 22:52:37 +010066
Tobias Woodf38e16c2023-11-29 11:12:48 +000067template <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;
71 typedef TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexType_> > Base;
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;
Benoit Steiner7402fea2014-05-16 15:08:05 -070078
Tobias Woodf38e16c2023-11-29 11:12:48 +000079 enum { IsAligned = (EIGEN_MAX_ALIGN_BYTES > 0) && !(Options_ & DontAlign), CoordAccess = true, RawAccess = true };
Christian Seilerf97b3cd2013-11-14 22:52:37 +010080
Tobias Woodf38e16c2023-11-29 11:12:48 +000081 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;
Benoit Steiner0320f7e2014-05-06 11:18:37 -070085
Tobias Woodf38e16c2023-11-29 11:12:48 +000086 protected:
87 TensorStorage<Scalar, Dimensions, Options> m_storage;
Christian Seilerf97b3cd2013-11-14 22:52:37 +010088
Tobias Woodf38e16c2023-11-29 11:12:48 +000089 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 };
Gabriel Nützi6edae2d2015-10-09 18:52:48 +020095
Tobias Woodf38e16c2023-11-29 11:12:48 +000096 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(); }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100104
Tobias Woodf38e16c2023-11-29 11:12:48 +0000105 // 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; }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100110
Tobias Woodf38e16c2023-11-29 11:12:48 +0000111 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100118
Tobias Woodf38e16c2023-11-29 11:12:48 +0000119 // 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100124
Tobias Woodf38e16c2023-11-29 11:12:48 +0000125 // 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 }
Gabriel Nützi6edae2d2015-10-09 18:52:48 +0200130
Tobias Woodf38e16c2023-11-29 11:12:48 +0000131 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 }
Benoit Steiner1c8312c2015-10-26 14:29:26 -0700135
Tobias Woodf38e16c2023-11-29 11:12:48 +0000136 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100140
Tobias Woodf38e16c2023-11-29 11:12:48 +0000141 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100147
Tobias Woodf38e16c2023-11-29 11:12:48 +0000148 // 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100153
Tobias Woodf38e16c2023-11-29 11:12:48 +0000154 // 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 }
Gabriel Nützi6edae2d2015-10-09 18:52:48 +0200159
Tobias Woodf38e16c2023-11-29 11:12:48 +0000160 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 }
Benoit Steiner1c8312c2015-10-26 14:29:26 -0700164
Tobias Woodf38e16c2023-11-29 11:12:48 +0000165 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100169
Tobias Woodf38e16c2023-11-29 11:12:48 +0000170 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100176
Tobias Woodf38e16c2023-11-29 11:12:48 +0000177 // 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 }
Gabriel Nützi6edae2d2015-10-09 18:52:48 +0200182
Tobias Woodf38e16c2023-11-29 11:12:48 +0000183 // normal indices
184 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const {
185 return coeff(indices);
186 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100187
Tobias Woodf38e16c2023-11-29 11:12:48 +0000188 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100192
Tobias Woodf38e16c2023-11-29 11:12:48 +0000193 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 }
Benoit Steiner1c8312c2015-10-26 14:29:26 -0700197
Tobias Woodf38e16c2023-11-29 11:12:48 +0000198 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100203
Tobias Woodf38e16c2023-11-29 11:12:48 +0000204 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100210
Tobias Woodf38e16c2023-11-29 11:12:48 +0000211 // normal indices
212 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices) {
213 return coeffRef(indices);
214 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100215
Tobias Woodf38e16c2023-11-29 11:12:48 +0000216 // 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 }
Gabriel Nützi6edae2d2015-10-09 18:52:48 +0200221
Tobias Woodf38e16c2023-11-29 11:12:48 +0000222 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index index) {
223 eigen_assert(index >= 0 && index < size());
224 return coeffRef(index);
225 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100226
Tobias Woodf38e16c2023-11-29 11:12:48 +0000227 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()() {
228 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
229 return coeffRef();
230 }
Benoit Steiner1c8312c2015-10-26 14:29:26 -0700231
Tobias Woodf38e16c2023-11-29 11:12:48 +0000232 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100237
Tobias Woodf38e16c2023-11-29 11:12:48 +0000238 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor() : m_storage() {}
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100239
Tobias Woodf38e16c2023-11-29 11:12:48 +0000240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(const Self& other) : Base(other), m_storage(other.m_storage) {}
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100241
Tyler Venessd165c732024-05-20 23:02:42 +0000242 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100248
Tyler Venessd165c732024-05-20 23:02:42 +0000249 /** Normal Dimension */
250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit Tensor(const array<Index, NumIndices>& dimensions)
251 : m_storage(internal::array_prod(dimensions), dimensions) {
Tobias Woodf38e16c2023-11-29 11:12:48 +0000252 EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
253 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100254
Tobias Woodf38e16c2023-11-29 11:12:48 +0000255 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)
258 typedef TensorAssignOp<Tensor, const OtherDerived> Assign;
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 }
Antonio Sanchez36694982020-11-12 15:59:29 -0800263
Tobias Woodf38e16c2023-11-29 11:12:48 +0000264 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 }
Benoit Steinerf50548e2014-09-04 19:50:27 -0700272
Tobias Woodf38e16c2023-11-29 11:12:48 +0000273 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 }
Viktor Csomor000840c2018-02-07 19:10:54 +0100278
Tobias Woodf38e16c2023-11-29 11:12:48 +0000279 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 }
Benoit Steinerc0f2cb02014-04-28 10:32:27 -0700294
Tobias Woodf38e16c2023-11-29 11:12:48 +0000295 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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100301
Tobias Woodf38e16c2023-11-29 11:12:48 +0000302 /** Normal Dimension */
303 EIGEN_DEVICE_FUNC void resize(const array<Index, NumIndices>& dimensions) {
Rasmus Munk Larsend3cd3122024-03-18 23:43:25 +0000304#ifndef EIGEN_NO_DEBUG
Tobias Woodf38e16c2023-11-29 11:12:48 +0000305 Index size = Index(1);
Rasmus Munk Larsend3cd3122024-03-18 23:43:25 +0000306 for (int i = 0; i < NumIndices; i++) {
Tobias Woodf38e16c2023-11-29 11:12:48 +0000307 internal::check_rows_cols_for_overflow<Dynamic, Dynamic, Dynamic>::run(size, dimensions[i]);
308 size *= dimensions[i];
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100309 }
Rasmus Munk Larsend3cd3122024-03-18 23:43:25 +0000310#else
311 Index size = internal::array_prod(dimensions);
312#endif
313
Tobias Woodf38e16c2023-11-29 11:12:48 +0000314#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 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100322
Tobias Woodf38e16c2023-11-29 11:12:48 +0000323 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 }
Benoit Steiner1c8312c2015-10-26 14:29:26 -0700327
Tobias Woodf38e16c2023-11-29 11:12:48 +0000328 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]);
Eugene Zhulenevc4627032018-09-18 14:25:21 -0700333 }
Tobias Woodf38e16c2023-11-29 11:12:48 +0000334 resize(dims);
335 }
Eugene Zhulenevc4627032018-09-18 14:25:21 -0700336
Tobias Woodf38e16c2023-11-29 11:12:48 +0000337 /** Custom Dimension */
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 }
Gabriel Nützi6edae2d2015-10-09 18:52:48 +0200342
Tobias Woodf38e16c2023-11-29 11:12:48 +0000343 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]);
Benoit Steinerf0ce85b2015-06-29 14:04:15 -0700348 }
Tobias Woodf38e16c2023-11-29 11:12:48 +0000349 resize(dims);
350 }
Benoit Steinerf0ce85b2015-06-29 14:04:15 -0700351
Tobias Woodf38e16c2023-11-29 11:12:48 +0000352#ifdef EIGEN_TENSOR_PLUGIN
353#include EIGEN_TENSOR_PLUGIN
354#endif
Turing Eret33243892021-08-30 19:36:55 +0000355
Tobias Woodf38e16c2023-11-29 11:12:48 +0000356 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;
Benoit Steiner0526dc12015-01-14 12:44:08 -0800363
Tobias Woodf38e16c2023-11-29 11:12:48 +0000364 return
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100365 // 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());
Tobias Woodf38e16c2023-11-29 11:12:48 +0000369 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100370
Tobias Woodf38e16c2023-11-29 11:12:48 +0000371 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);
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100376 }
Tobias Woodf38e16c2023-11-29 11:12:48 +0000377 }
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100378};
379
Tobias Woodf38e16c2023-11-29 11:12:48 +0000380} // end namespace Eigen
Christian Seilerf97b3cd2013-11-14 22:52:37 +0100381
Tobias Woodf38e16c2023-11-29 11:12:48 +0000382#endif // EIGEN_CXX11_TENSOR_TENSOR_H