69class Tensor :
public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexType_> > {
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;
78 typedef typename Base::CoeffReturnType CoeffReturnType;
80 enum { IsAligned = (EIGEN_MAX_ALIGN_BYTES > 0) && !(Options_ &
DontAlign), CoordAccess =
true, RawAccess =
true };
83 static constexpr int Options = Options_;
84 static constexpr int NumIndices = NumIndices_;
85 typedef DSizes<Index, NumIndices_> Dimensions;
88 TensorStorage<Scalar, Dimensions, Options> m_storage;
90 template <
typename CustomIndices>
91 struct isOfNormalIndex {
92 static constexpr bool is_array = std::is_base_of<array<Index, NumIndices>, CustomIndices>::value;
94 static constexpr bool value = is_array | is_int;
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(); }
109 inline Self& base() {
return *
this; }
110 inline const Self& base()
const {
return *
this; }
112 template <
typename... IndexTypes>
113 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar& coeff(Index firstIndex, Index secondIndex,
114 IndexTypes... otherIndices)
const {
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)...}});
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)];
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));
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];
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];
143 template <
typename... IndexTypes>
144 inline Scalar& coeffRef(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) {
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)...}});
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)];
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));
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];
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];
173 template <
typename... IndexTypes>
174 inline const Scalar& operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices)
const {
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)...}});
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));
188 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar& operator()(
const array<Index, NumIndices>& indices)
const {
189 return coeff(indices);
192 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar& operator()(Index index)
const {
193 eigen_internal_assert(index >= 0 && index < size());
197 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar& operator()()
const {
198 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
202 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar& operator[](Index index)
const {
204 EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
208 template <
typename... IndexTypes>
209 inline Scalar& operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) {
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)...}});
217 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(
const array<Index, NumIndices>& indices) {
218 return coeffRef(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));
227 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index index) {
228 eigen_assert(index >= 0 && index < size());
229 return coeffRef(index);
232 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()() {
233 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
237 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator[](Index index) {
239 EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE)
240 return coeffRef(index);
243 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor() : m_storage() {}
245 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(
const Self& other) =
default;
247 template <
typename... IndexTypes>
248 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(Index firstDimension, IndexTypes... otherDimensions)
249 : m_storage(firstDimension, otherDimensions...) {
251 EIGEN_STATIC_ASSERT(
sizeof...(otherDimensions) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
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
260 template <
typename OtherDerived>
262 EIGEN_STATIC_ASSERT(OtherDerived::NumDimensions == Base::NumDimensions, Number_of_dimensions_must_match)
264 Assign assign(*
this, other.derived());
266 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
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());
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);
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());
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());
300 template <
typename... IndexTypes>
301 EIGEN_DEVICE_FUNC
void resize(Index firstDimension, IndexTypes... otherDimensions) {
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)...}});
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];
317 Index size = internal::array_prod(dimensions);
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
325 m_storage.resize(size, dimensions);
329 EIGEN_DEVICE_FUNC
void resize() {
330 EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
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]);
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));
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]);
358#ifdef EIGEN_TENSOR_PLUGIN
359#include EIGEN_TENSOR_PLUGIN
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;
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);
374 return m_storage.dimensions().IndexOfColMajor(indices);