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  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 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
94  template<typename... IndexTypes>
95  inline Scalar& coeffRef(Index firstIndex, IndexTypes... otherIndices)
96  {
97  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
98  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
99  return coeffRef(array<Index, NumIndices>{{firstIndex, otherIndices...}});
100  }
101 #endif
102 
103  EIGEN_DEVICE_FUNC
104  EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices)
105  {
106  eigen_internal_assert(checkIndexRange(indices));
107  return m_storage.data()[linearizedIndex(indices)];
108  }
109 
110  EIGEN_DEVICE_FUNC
111  EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
112  {
113  eigen_internal_assert(index >= 0 && index < size());
114  return m_storage.data()[index];
115  }
116 
117 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
118  template<typename... IndexTypes>
119  inline const Scalar& operator()(Index firstIndex, IndexTypes... otherIndices) const
120  {
121  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
122  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
123  return this->operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
124  }
125 #endif
126 
127  EIGEN_DEVICE_FUNC
128  EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const
129  {
130  eigen_assert(checkIndexRange(indices));
131  return coeff(indices);
132  }
133 
134  EIGEN_DEVICE_FUNC
135  EIGEN_STRONG_INLINE const Scalar& operator()(Index index) const
136  {
137  eigen_internal_assert(index >= 0 && index < size());
138  return coeff(index);
139  }
140 
141  EIGEN_DEVICE_FUNC
142  EIGEN_STRONG_INLINE const Scalar& operator[](Index index) const
143  {
144  // The bracket operator is only for vectors, use the parenthesis operator instead.
145  EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
146  return coeff(index);
147  }
148 
149 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
150  template<typename... IndexTypes>
151  inline Scalar& operator()(Index firstIndex, IndexTypes... otherIndices)
152  {
153  // The number of indices used to access a tensor coefficient must be equal to the rank of the tensor.
154  EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 1 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE)
155  return operator()(array<Index, NumIndices>{{firstIndex, otherIndices...}});
156  }
157 #endif
158 
159  EIGEN_DEVICE_FUNC
160  EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices)
161  {
162  eigen_assert(checkIndexRange(indices));
163  return coeffRef(indices);
164  }
165 
166  EIGEN_DEVICE_FUNC
167  EIGEN_STRONG_INLINE Scalar& operator()(Index index)
168  {
169  eigen_assert(index >= 0 && index < size());
170  return coeffRef(index);
171  }
172 
173  EIGEN_DEVICE_FUNC
174  EIGEN_STRONG_INLINE Scalar& operator[](Index index)
175  {
176  // The bracket operator is only for vectors, use the parenthesis operator instead
177  EIGEN_STATIC_ASSERT(NumIndices == 1, YOU_MADE_A_PROGRAMMING_MISTAKE)
178  return coeffRef(index);
179  }
180 
181  EIGEN_DEVICE_FUNC
182  EIGEN_STRONG_INLINE TensorFixedSize()
183  : m_storage()
184  {
185  }
186 
187  EIGEN_DEVICE_FUNC
188  EIGEN_STRONG_INLINE TensorFixedSize(const Self& other)
189  : m_storage(other.m_storage)
190  {
191  }
192 
193 #ifdef EIGEN_HAVE_RVALUE_REFERENCES
194  inline TensorFixedSize(Self&& other)
195  : m_storage(other.m_storage)
196  {
197  }
198 #endif
199 
200  template<typename OtherDerived>
201  EIGEN_DEVICE_FUNC
202  EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, ReadOnlyAccessors>& other)
203  {
204  typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
205  Assign assign(*this, other.derived());
206  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
207  }
208  template<typename OtherDerived>
209  EIGEN_DEVICE_FUNC
210  EIGEN_STRONG_INLINE TensorFixedSize(const TensorBase<OtherDerived, WriteAccessors>& other)
211  {
212  typedef TensorAssignOp<TensorFixedSize, const OtherDerived> Assign;
213  Assign assign(*this, other.derived());
214  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
215  }
216 
217  EIGEN_DEVICE_FUNC
218  EIGEN_STRONG_INLINE TensorFixedSize& operator=(const TensorFixedSize& other)
219  {
220  // FIXME: check that the dimensions of other match the dimensions of *this.
221  // Unfortunately this isn't possible yet when the rhs is an expression.
222  typedef TensorAssignOp<Self, const TensorFixedSize> Assign;
223  Assign assign(*this, other);
224  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
225  return *this;
226  }
227  template<typename OtherDerived>
228  EIGEN_DEVICE_FUNC
229  EIGEN_STRONG_INLINE TensorFixedSize& operator=(const OtherDerived& other)
230  {
231  // FIXME: check that the dimensions of other match the dimensions of *this.
232  // Unfortunately this isn't possible yet when the rhs is an expression.
233  typedef TensorAssignOp<Self, const OtherDerived> Assign;
234  Assign assign(*this, other);
235  internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
236  return *this;
237  }
238 
239  protected:
240  EIGEN_DEVICE_FUNC
241  EIGEN_STRONG_INLINE bool checkIndexRange(const array<Index, NumIndices>& /*indices*/) const
242  {
243  using internal::array_apply_and_reduce;
244  using internal::array_zip_and_reduce;
245  using internal::greater_equal_zero_op;
246  using internal::logical_and_op;
247  using internal::lesser_op;
248 
249  return true;
250  // check whether the indices are all >= 0
251  /* array_apply_and_reduce<logical_and_op, greater_equal_zero_op>(indices) &&
252  // check whether the indices fit in the dimensions
253  array_zip_and_reduce<logical_and_op, lesser_op>(indices, m_storage.dimensions());*/
254  }
255 
256  EIGEN_DEVICE_FUNC
257  EIGEN_STRONG_INLINE Index linearizedIndex(const array<Index, NumIndices>& indices) const
258  {
259  if (Options&RowMajor) {
260  return m_storage.dimensions().IndexOfRowMajor(indices);
261  } else {
262  return m_storage.dimensions().IndexOfColMajor(indices);
263  }
264  }
265 };
266 
267 
268 } // end namespace Eigen
269 
270 #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