xref: /aosp_15_r20/external/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorFixedSize.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <[email protected]>
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_FIXED_SIZE_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_FIXED_SIZE_H
12 
13 namespace Eigen {
14 
15 /** \class TensorFixedSize
16   * \ingroup CXX11_Tensor_Module
17   *
18   * \brief The fixed sized version of the tensor class.
19   *
20   * The fixed sized equivalent of
21   * Eigen::Tensor<float, 3> t(3, 5, 7);
22   * is
23   * Eigen::TensorFixedSize<float, Sizes<3,5,7>> t;
24   */
25 
26 template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType>
27 class TensorFixedSize : public TensorBase<TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType> >
28 {
29   public:
30     typedef TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType> Self;
31     typedef TensorBase<TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType> > Base;
32     typedef typename Eigen::internal::nested<Self>::type Nested;
33     typedef typename internal::traits<Self>::StorageKind StorageKind;
34     typedef typename internal::traits<Self>::Index Index;
35     typedef Scalar_ Scalar;
36     typedef typename NumTraits<Scalar>::Real RealScalar;
37     typedef typename Base::CoeffReturnType CoeffReturnType;
38 
39     static const int Options = Options_;
40 
41     enum {
42       IsAligned = bool(EIGEN_MAX_ALIGN_BYTES>0),
43       PacketAccess = (internal::packet_traits<Scalar>::size > 1),
44       BlockAccess = false,
45       PreferBlockAccess = false,
46       Layout = Options_ & RowMajor ? RowMajor : ColMajor,
47       CoordAccess = true,
48       RawAccess = true
49     };
50 
51   //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
52   typedef internal::TensorBlockNotImplemented TensorBlock;
53   //===--------------------------------------------------------------------===//
54 
55   typedef Dimensions_ Dimensions;
56   static const std::size_t NumIndices = Dimensions::count;
57 
58   protected:
59   TensorStorage<Scalar, Dimensions, Options> m_storage;
60 
61   public:
rank()62     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index                    rank()                   const { return NumIndices; }
dimension(std::size_t n)63     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index                    dimension(std::size_t n) const { return m_storage.dimensions()[n]; }
dimensions()64     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions&        dimensions()             const { return m_storage.dimensions(); }
size()65     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index                    size()                   const { return m_storage.size(); }
data()66     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar                   *data()                        { return m_storage.data(); }
data()67     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar             *data()                  const { return m_storage.data(); }
68 
69     // This makes EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
70     // work, because that uses base().coeffRef() - and we don't yet
71     // implement a similar class hierarchy
base()72     inline Self& base()             { return *this; }
base()73     inline const Self& base() const { return *this; }
74 
75 #if EIGEN_HAS_VARIADIC_TEMPLATES
76     template<typename... IndexTypes>
coeff(Index firstIndex,IndexTypes...otherIndices)77     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index firstIndex, IndexTypes... otherIndices) const
78     {
79       // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
80       EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
81       return coeff(array<Index, NumIndices>{{firstIndex, otherIndices...}});
82     }
83 #endif
84 
85     EIGEN_DEVICE_FUNC
coeff(const array<Index,NumIndices> & indices)86     EIGEN_STRONG_INLINE const Scalar& coeff(const array<Index, NumIndices>& indices) const
87     {
88       eigen_internal_assert(checkIndexRange(indices));
89       return m_storage.data()[linearizedIndex(indices)];
90     }
91 
92     EIGEN_DEVICE_FUNC
coeff(Index index)93     EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
94     {
95       eigen_internal_assert(index >= 0 && index < size());
96       return m_storage.data()[index];
97     }
98 
99     EIGEN_DEVICE_FUNC
coeff()100     EIGEN_STRONG_INLINE const Scalar& coeff() const
101     {
102       EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
103       return m_storage.data()[0];
104     }
105 
106 
107 #if EIGEN_HAS_VARIADIC_TEMPLATES
108     template<typename... IndexTypes>
coeffRef(Index firstIndex,IndexTypes...otherIndices)109     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index firstIndex, IndexTypes... otherIndices)
110     {
111       // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
112       EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
113       return coeffRef(array<Index, NumIndices>{{firstIndex, otherIndices...}});
114     }
115 #endif
116 
117     EIGEN_DEVICE_FUNC
coeffRef(const array<Index,NumIndices> & indices)118     EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices)
119     {
120       eigen_internal_assert(checkIndexRange(indices));
121       return m_storage.data()[linearizedIndex(indices)];
122     }
123 
124     EIGEN_DEVICE_FUNC
coeffRef(Index index)125     EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
126     {
127       eigen_internal_assert(index >= 0 && index < size());
128       return m_storage.data()[index];
129     }
130 
131     EIGEN_DEVICE_FUNC
coeffRef()132     EIGEN_STRONG_INLINE Scalar& coeffRef()
133     {
134       EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
135       return m_storage.data()[0];
136     }
137 
138 #if EIGEN_HAS_VARIADIC_TEMPLATES
139     template<typename... IndexTypes>
operator()140     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(Index firstIndex, IndexTypes... otherIndices) const
141     {
142       // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
143       EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
144       return this->operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
145     }
146 #else
147     EIGEN_DEVICE_FUNC
operator()148     EIGEN_STRONG_INLINE const Scalar& operator()(Index i0, Index i1) const
149     {
150       if (Options&RowMajor) {
151         const Index index = i1 + i0 * m_storage.dimensions()[1];
152         return m_storage.data()[index];
153       } else {
154         const Index index = i0 + i1 * m_storage.dimensions()[0];
155         return m_storage.data()[index];
156       }
157     }
158     EIGEN_DEVICE_FUNC
operator()159     EIGEN_STRONG_INLINE const Scalar& operator()(Index i0, Index i1, Index i2) const
160     {
161       if (Options&RowMajor) {
162          const Index index = i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0);
163          return m_storage.data()[index];
164       } else {
165          const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * i2);
166         return m_storage.data()[index];
167       }
168     }
169     EIGEN_DEVICE_FUNC
operator()170     EIGEN_STRONG_INLINE const Scalar& operator()(Index i0, Index i1, Index i2, Index i3) const
171     {
172       if (Options&RowMajor) {
173         const Index index = i3 + m_storage.dimensions()[3] * (i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0));
174         return m_storage.data()[index];
175       } else {
176         const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * (i2 + m_storage.dimensions()[2] * i3));
177         return m_storage.data()[index];
178       }
179     }
180     EIGEN_DEVICE_FUNC
operator()181     EIGEN_STRONG_INLINE const Scalar& operator()(Index i0, Index i1, Index i2, Index i3, Index i4) const
182     {
183       if (Options&RowMajor) {
184         const Index index = i4 + m_storage.dimensions()[4] * (i3 + m_storage.dimensions()[3] * (i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0)));
185         return m_storage.data()[index];
186       } else {
187         const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * (i2 + m_storage.dimensions()[2] * (i3 + m_storage.dimensions()[3] * i4)));
188         return m_storage.data()[index];
189       }
190     }
191 #endif
192 
193 
194     EIGEN_DEVICE_FUNC
operator()195     EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const
196     {
197       eigen_assert(checkIndexRange(indices));
198       return coeff(indices);
199     }
200 
201     EIGEN_DEVICE_FUNC
operator()202     EIGEN_STRONG_INLINE const Scalar& operator()(Index index) const
203     {
204       eigen_internal_assert(index >= 0 && index < size());
205       return coeff(index);
206     }
207 
208     EIGEN_DEVICE_FUNC
operator()209     EIGEN_STRONG_INLINE const Scalar& operator()() const
210     {
211       EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
212       return coeff();
213     }
214 
215     EIGEN_DEVICE_FUNC
216     EIGEN_STRONG_INLINE const Scalar& operator[](Index index) const
217     {
218       // The bracket operator is only for vectors, use the parenthesis operator instead.
219       EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
220       return coeff(index);
221     }
222 
223 #if EIGEN_HAS_VARIADIC_TEMPLATES
224     template<typename... IndexTypes>
operator()225     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index firstIndex, IndexTypes... otherIndices)
226     {
227       // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
228       EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
229       return operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
230     }
231 #else
232     EIGEN_DEVICE_FUNC
operator()233     EIGEN_STRONG_INLINE Scalar& operator()(Index i0, Index i1)
234     {
235        if (Options&RowMajor) {
236          const Index index = i1 + i0 * m_storage.dimensions()[1];
237         return m_storage.data()[index];
238       } else {
239         const Index index = i0 + i1 * m_storage.dimensions()[0];
240         return m_storage.data()[index];
241       }
242     }
243     EIGEN_DEVICE_FUNC
operator()244     EIGEN_STRONG_INLINE Scalar& operator()(Index i0, Index i1, Index i2)
245     {
246        if (Options&RowMajor) {
247          const Index index = i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0);
248         return m_storage.data()[index];
249       } else {
250          const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * i2);
251         return m_storage.data()[index];
252       }
253     }
254     EIGEN_DEVICE_FUNC
operator()255     EIGEN_STRONG_INLINE Scalar& operator()(Index i0, Index i1, Index i2, Index i3)
256     {
257       if (Options&RowMajor) {
258         const Index index = i3 + m_storage.dimensions()[3] * (i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0));
259         return m_storage.data()[index];
260       } else {
261         const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * (i2 + m_storage.dimensions()[2] * i3));
262         return m_storage.data()[index];
263       }
264     }
265     EIGEN_DEVICE_FUNC
operator()266     EIGEN_STRONG_INLINE Scalar& operator()(Index i0, Index i1, Index i2, Index i3, Index i4)
267     {
268       if (Options&RowMajor) {
269         const Index index = i4 + m_storage.dimensions()[4] * (i3 + m_storage.dimensions()[3] * (i2 + m_storage.dimensions()[2] * (i1 + m_storage.dimensions()[1] * i0)));
270         return m_storage.data()[index];
271       } else {
272         const Index index = i0 + m_storage.dimensions()[0] * (i1 + m_storage.dimensions()[1] * (i2 + m_storage.dimensions()[2] * (i3 + m_storage.dimensions()[3] * i4)));
273         return m_storage.data()[index];
274       }
275     }
276 #endif
277 
278     EIGEN_DEVICE_FUNC
operator()279     EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices)
280     {
281       eigen_assert(checkIndexRange(indices));
282       return coeffRef(indices);
283     }
284 
285     EIGEN_DEVICE_FUNC
operator()286     EIGEN_STRONG_INLINE Scalar& operator()(Index index)
287     {
288       eigen_assert(index >= 0 && index < size());
289       return coeffRef(index);
290     }
291 
292     EIGEN_DEVICE_FUNC
operator()293     EIGEN_STRONG_INLINE Scalar& operator()()
294     {
295       EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
296       return coeffRef();
297     }
298 
299     EIGEN_DEVICE_FUNC
300     EIGEN_STRONG_INLINE Scalar& operator[](Index index)
301     {
302       // The bracket operator is only for vectors, use the parenthesis operator instead
303       EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE)
304       return coeffRef(index);
305     }
306 
307     EIGEN_DEVICE_FUNC
TensorFixedSize()308     EIGEN_STRONG_INLINE TensorFixedSize()
309       : m_storage()
310     {
311     }
312 
313     EIGEN_DEVICE_FUNC
TensorFixedSize(const Self & other)314     EIGEN_STRONG_INLINE TensorFixedSize(const Self& other)
315       : m_storage(other.m_storage)
316     {
317     }
318 
319 #if EIGEN_HAS_RVALUE_REFERENCES
TensorFixedSize(Self && other)320     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorFixedSize(Self&& other)
321       : m_storage(other.m_storage)
322     {
323     }
324 #endif
325 
326     template<typename OtherDerived>
327     EIGEN_DEVICE_FUNC
TensorFixedSize(const TensorBase<OtherDerived,ReadOnlyAccessors> & other)328     EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, ReadOnlyAccessors>& other)
329     {
330       typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
331       Assign assign(*this, other.derived());
332       internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
333     }
334     template<typename OtherDerived>
335     EIGEN_DEVICE_FUNC
TensorFixedSize(const TensorBase<OtherDerived,WriteAccessors> & other)336     EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, WriteAccessors>& other)
337     {
338       typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
339       Assign assign(*this, other.derived());
340       internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
341     }
342 
343     // FIXME: check that the dimensions of other match the dimensions of *this.
344     // Unfortunately this isn't possible yet when the rhs is an expression.
EIGEN_TENSOR_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(TensorFixedSize)345     EIGEN_TENSOR_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(TensorFixedSize)
346 
347 
348   protected:
349     EIGEN_DEVICE_FUNC
350     EIGEN_STRONG_INLINE bool checkIndexRange(const array<Index, NumIndices>& /*indices*/) const
351     {
352       using internal::array_apply_and_reduce;
353       using internal::array_zip_and_reduce;
354       using internal::greater_equal_zero_op;
355       using internal::logical_and_op;
356       using internal::lesser_op;
357 
358       return true;
359         // check whether the indices are all >= 0
360           /*       array_apply_and_reduce<logical_and_op, greater_equal_zero_op>(indices) &&
361         // check whether the indices fit in the dimensions
362         array_zip_and_reduce<logical_and_op, lesser_op>(indices, m_storage.dimensions());*/
363     }
364 
365     EIGEN_DEVICE_FUNC
linearizedIndex(const array<Index,NumIndices> & indices)366     EIGEN_STRONG_INLINE Index linearizedIndex(const array<Index, NumIndices>& indices) const
367     {
368       if (Options&RowMajor) {
369         return m_storage.dimensions().IndexOfRowMajor(indices);
370       } else {
371         return m_storage.dimensions().IndexOfColMajor(indices);
372       }
373     }
374 };
375 
376 
377 } // end namespace Eigen
378 
379 #endif // EIGEN_CXX11_TENSOR_TENSOR_FIXED_SIZE_H
380