TensorFixedSize.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 //
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 
26 template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType>
27 class TensorFixedSize : public TensorBase<TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType> >
28 {
29  public:
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 internal::packet_traits<Scalar>::type Packet;
37  typedef typename NumTraits<Scalar>::Real RealScalar;
38  typedef typename Base::CoeffReturnType CoeffReturnType;
39 
40  static const int Options = Options_;
41 
42  enum {
43  IsAligned = bool(EIGEN_MAX_ALIGN_BYTES>0),
44  PacketAccess = (internal::packet_traits<Scalar>::size > 1),
45  Layout = Options_ & RowMajor ? RowMajor : ColMajor,
46  CoordAccess = true,
47  };
48 
49  typedef Dimensions_ Dimensions;
50  static const std::size_t NumIndices = Dimensions::count;
51 
52  protected:
53  TensorStorage<Scalar, Dimensions, Options> m_storage;
54 
55  public:
56  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rank() const { return NumIndices; }
57  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index dimension(std::size_t n) const { return m_storage.dimensions()[n]; }
58  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_storage.dimensions(); }
59  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return m_storage.size(); }
60  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar *data() { return m_storage.data(); }
61  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar *data() const { return m_storage.data(); }
62 
63  // This makes EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
64  // work, because that uses base().coeffRef() - and we don't yet
65  // implement a similar class hierarchy
66  inline Self& base() { return *this; }
67  inline const Self& base() const { return *this; }
68 
69 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
70  template<typename... IndexTypes>
71  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index firstIndex, IndexTypes... otherIndices) const
72  {
73  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
74  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
75  return coeff(array<Index, NumIndices>{{firstIndex, otherIndices...}});
76  }
77 #endif
78 
79  EIGEN_DEVICE_FUNC
80  EIGEN_STRONG_INLINE const Scalar& coeff(const array<Index, NumIndices>& indices) const
81  {
82  eigen_internal_assert(checkIndexRange(indices));
83  return m_storage.data()[linearizedIndex(indices)];
84  }
85 
86  EIGEN_DEVICE_FUNC
87  EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
88  {
89  eigen_internal_assert(index >= 0 && index < size());
90  return m_storage.data()[index];
91  }
92 
93  EIGEN_DEVICE_FUNC
94  EIGEN_STRONG_INLINE const Scalar& coeff() const
95  {
96  EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
97  return m_storage.data()[0];
98  }
99 
100 
101 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
102  template<typename... IndexTypes>
103  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index firstIndex, IndexTypes... otherIndices)
104  {
105  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
106  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
107  return coeffRef(array<Index, NumIndices>{{firstIndex, otherIndices...}});
108  }
109 #endif
110 
111  EIGEN_DEVICE_FUNC
112  EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices)
113  {
114  eigen_internal_assert(checkIndexRange(indices));
115  return m_storage.data()[linearizedIndex(indices)];
116  }
117 
118  EIGEN_DEVICE_FUNC
119  EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
120  {
121  eigen_internal_assert(index >= 0 && index < size());
122  return m_storage.data()[index];
123  }
124 
125  EIGEN_DEVICE_FUNC
126  EIGEN_STRONG_INLINE Scalar& coeffRef()
127  {
128  EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
129  return m_storage.data()[0];
130  }
131 
132 
133 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
134  template<typename... IndexTypes>
135  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(Index firstIndex, IndexTypes... otherIndices) const
136  {
137  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
138  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
139  return this->operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
140  }
141 #endif
142 
143  EIGEN_DEVICE_FUNC
144  EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const
145  {
146  eigen_assert(checkIndexRange(indices));
147  return coeff(indices);
148  }
149 
150  EIGEN_DEVICE_FUNC
151  EIGEN_STRONG_INLINE const Scalar& operator()(Index index) const
152  {
153  eigen_internal_assert(index >= 0 && index < size());
154  return coeff(index);
155  }
156 
157  EIGEN_DEVICE_FUNC
158  EIGEN_STRONG_INLINE const Scalar& operator()() const
159  {
160  EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
161  return coeff();
162  }
163 
164  EIGEN_DEVICE_FUNC
165  EIGEN_STRONG_INLINE const Scalar& operator[](Index index) const
166  {
167  // The bracket operator is only for vectors, use the parenthesis operator instead.
168  EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
169  return coeff(index);
170  }
171 
172 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
173  template<typename... IndexTypes>
174  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index firstIndex, IndexTypes... otherIndices)
175  {
176  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
177  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
178  return operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
179  }
180 #endif
181 
182  EIGEN_DEVICE_FUNC
183  EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices)
184  {
185  eigen_assert(checkIndexRange(indices));
186  return coeffRef(indices);
187  }
188 
189  EIGEN_DEVICE_FUNC
190  EIGEN_STRONG_INLINE Scalar& operator()(Index index)
191  {
192  eigen_assert(index >= 0 && index < size());
193  return coeffRef(index);
194  }
195 
196  EIGEN_DEVICE_FUNC
197  EIGEN_STRONG_INLINE Scalar& operator()()
198  {
199  EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE);
200  return coeffRef();
201  }
202 
203  EIGEN_DEVICE_FUNC
204  EIGEN_STRONG_INLINE Scalar& operator[](Index index)
205  {
206  // The bracket operator is only for vectors, use the parenthesis operator instead
207  EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE)
208  return coeffRef(index);
209  }
210 
211  EIGEN_DEVICE_FUNC
212  EIGEN_STRONG_INLINE TensorFixedSize()
213  : m_storage()
214  {
215  }
216 
217  EIGEN_DEVICE_FUNC
218  EIGEN_STRONG_INLINE TensorFixedSize(const Self& other)
219  : m_storage(other.m_storage)
220  {
221  }
222 
223 #ifdef EIGEN_HAVE_RVALUE_REFERENCES
224  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorFixedSize(Self&& other)
225  : m_storage(other.m_storage)
226  {
227  }
228 #endif
229 
230  template<typename OtherDerived>
231  EIGEN_DEVICE_FUNC
232  EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, ReadOnlyAccessors>& other)
233  {
234  typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
235  Assign assign(*this, other.derived());
236  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
237  }
238  template<typename OtherDerived>
239  EIGEN_DEVICE_FUNC
240  EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, WriteAccessors>& other)
241  {
242  typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
243  Assign assign(*this, other.derived());
244  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
245  }
246 
247  EIGEN_DEVICE_FUNC
248  EIGEN_STRONG_INLINE TensorFixedSize& operator=(const TensorFixedSize& other)
249  {
250  // FIXME: check that the dimensions of other match the dimensions of *this.
251  // Unfortunately this isn't possible yet when the rhs is an expression.
252  typedef TensorAssignOp<Self, const TensorFixedSize> Assign;
253  Assign assign(*this, other);
254  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
255  return *this;
256  }
257  template<typename OtherDerived>
258  EIGEN_DEVICE_FUNC
259  EIGEN_STRONG_INLINE TensorFixedSize& operator=(const OtherDerived& other)
260  {
261  // FIXME: check that the dimensions of other match the dimensions of *this.
262  // Unfortunately this isn't possible yet when the rhs is an expression.
263  typedef TensorAssignOp<Self, const OtherDerived> Assign;
264  Assign assign(*this, other);
265  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
266  return *this;
267  }
268 
269  protected:
270  EIGEN_DEVICE_FUNC
271  EIGEN_STRONG_INLINE bool checkIndexRange(const array<Index, NumIndices>& /*indices*/) const
272  {
273  using internal::array_apply_and_reduce;
274  using internal::array_zip_and_reduce;
275  using internal::greater_equal_zero_op;
276  using internal::logical_and_op;
277  using internal::lesser_op;
278 
279  return true;
280  // check whether the indices are all >= 0
281  /* array_apply_and_reduce<logical_and_op, greater_equal_zero_op>(indices) &&
282  // check whether the indices fit in the dimensions
283  array_zip_and_reduce<logical_and_op, lesser_op>(indices, m_storage.dimensions());*/
284  }
285 
286  EIGEN_DEVICE_FUNC
287  EIGEN_STRONG_INLINE Index linearizedIndex(const array<Index, NumIndices>& indices) const
288  {
289  if (Options&RowMajor) {
290  return m_storage.dimensions().IndexOfRowMajor(indices);
291  } else {
292  return m_storage.dimensions().IndexOfColMajor(indices);
293  }
294  }
295 };
296 
297 
298 } // end namespace Eigen
299 
300 #endif // EIGEN_CXX11_TENSOR_TENSOR_FIXED_SIZE_H
Namespace containing all symbols from the Eigen library.
Definition: CXX11Meta.h:13
The fixed sized version of the tensor class.
Definition: TensorFixedSize.h:27
The tensor base class.
Definition: TensorForwardDeclarations.h:19