TensorDimensions.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_DIMENSIONS_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_DIMENSIONS_H
12 
13 
14 namespace Eigen {
15 
32 // Can't use std::pair on cuda devices
33 template <typename Index> struct IndexPair {
34  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE IndexPair() : first(0), second(0) { }
35  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE IndexPair(Index f, Index s) : first(f), second(s) { }
36  Index first;
37  Index second;
38 };
39 
40 // Boilerplate code
41 namespace internal {
42 
43 template<std::size_t n, typename Dimension> struct dget {
44  static const std::size_t value = get<n, Dimension>::value;
45 };
46 
47 
48 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor>
49 struct fixed_size_tensor_index_linearization_helper
50 {
51  template <typename Dimensions> EIGEN_DEVICE_FUNC
52  static inline Index run(array<Index, NumIndices> const& indices,
53  const Dimensions& dimensions)
54  {
55  return array_get<RowMajor ? n - 1 : (NumIndices - n)>(indices) +
56  dget<RowMajor ? n - 1 : (NumIndices - n), Dimensions>::value *
57  fixed_size_tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
58  }
59 };
60 
61 template<typename Index, std::size_t NumIndices, bool RowMajor>
62 struct fixed_size_tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor>
63 {
64  template <typename Dimensions> EIGEN_DEVICE_FUNC
65  static inline Index run(array<Index, NumIndices> const&, const Dimensions&)
66  {
67  return 0;
68  }
69 };
70 
71 template<typename Index, std::size_t n>
72 struct fixed_size_tensor_index_extraction_helper
73 {
74  template <typename Dimensions> EIGEN_DEVICE_FUNC
75  static inline Index run(const Index index,
76  const Dimensions& dimensions)
77  {
78  const Index mult = (index == n-1) ? 1 : 0;
79  return array_get<n-1>(dimensions) * mult +
80  fixed_size_tensor_index_extraction_helper<Index, n - 1>::run(index, dimensions);
81  }
82 };
83 
84 template<typename Index>
85 struct fixed_size_tensor_index_extraction_helper<Index, 0>
86 {
87  template <typename Dimensions> EIGEN_DEVICE_FUNC
88  static inline Index run(const Index,
89  const Dimensions&)
90  {
91  return 0;
92  }
93  };
94 
95 } // end namespace internal
96 
97 
98 // Fixed size
99 #ifndef EIGEN_EMULATE_CXX11_META_H
100 template <typename std::ptrdiff_t... Indices>
101 struct Sizes : internal::numeric_list<std::ptrdiff_t, Indices...> {
102  typedef internal::numeric_list<std::ptrdiff_t, Indices...> Base;
103  static const std::ptrdiff_t total_size = internal::arg_prod(Indices...);
104 
105  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t rank() const {
106  return Base::count;
107  }
108 
109  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t TotalSize() {
110  return internal::arg_prod(Indices...);
111  }
112 
113  Sizes() { }
114  template <typename DenseIndex>
115  explicit Sizes(const array<DenseIndex, Base::count>& /*indices*/) {
116  // todo: add assertion
117  }
118 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
119  template <typename... DenseIndex> Sizes(DenseIndex...) { }
120  explicit Sizes(std::initializer_list<std::ptrdiff_t> /*l*/) {
121  // todo: add assertion
122  }
123 #endif
124 
125  template <typename T> Sizes& operator = (const T& /*other*/) {
126  // add assertion failure if the size of other is different
127  return *this;
128  }
129 
130  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t operator[] (const std::size_t index) const {
131  return internal::fixed_size_tensor_index_extraction_helper<std::ptrdiff_t, Base::count>::run(index, *this);
132  }
133 
134  template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
135  size_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const {
136  return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, *static_cast<const Base*>(this));
137  }
138  template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
139  size_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const {
140  return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, *static_cast<const Base*>(this));
141  }
142 };
143 
144 namespace internal {
145 template <typename std::ptrdiff_t... Indices>
146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_prod(const Sizes<Indices...>&) {
147  return Sizes<Indices...>::total_size;
148 }
149 }
150 
151 #else
152 
153 template <std::size_t n>
154 struct non_zero_size {
155  typedef internal::type2val<std::size_t, n> type;
156 };
157 template <>
158 struct non_zero_size<0> {
159  typedef internal::null_type type;
160 };
161 
162 template <std::size_t V1=0, std::size_t V2=0, std::size_t V3=0, std::size_t V4=0, std::size_t V5=0> struct Sizes {
163  typedef typename internal::make_type_list<typename non_zero_size<V1>::type, typename non_zero_size<V2>::type, typename non_zero_size<V3>::type, typename non_zero_size<V4>::type, typename non_zero_size<V5>::type >::type Base;
164  static const size_t count = Base::count;
165  static const std::size_t total_size = internal::arg_prod<Base>::value;
166 
167  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t rank() const {
168  return count;
169  }
170 
171  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t TotalSize() {
172  return internal::arg_prod<Base>::value;
173  }
174 
175  Sizes() { }
176  template <typename DenseIndex>
177  explicit Sizes(const array<DenseIndex, Base::count>& /*indices*/) {
178  // todo: add assertion
179  }
180  template <typename T> Sizes& operator = (const T& /*other*/) {
181  // add assertion failure if the size of other is different
182  return *this;
183  }
184 
185 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
186  template <typename... DenseIndex> Sizes(DenseIndex... /*indices*/) { }
187  explicit Sizes(std::initializer_list<std::size_t>) {
188  // todo: add assertion
189  }
190 #else
191  EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex) {
192  }
193  EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex, const DenseIndex) {
194  }
195  EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex, const DenseIndex, const DenseIndex) {
196  }
197  EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) {
198  }
199  EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) {
200  }
201 #endif
202 
203  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex operator[] (const int index) const {
204  switch (index) {
205  case 0:
206  return internal::get<0, Base>::value;
207  case 1:
208  return internal::get<1, Base>::value;
209  case 2:
210  return internal::get<2, Base>::value;
211  case 3:
212  return internal::get<3, Base>::value;
213  case 4:
214  return internal::get<4, Base>::value;
215  default:
216  eigen_assert(false && "index overflow");
217  return static_cast<DenseIndex>(-1);
218  }
219  }
220 
221  template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
222  size_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const {
223  return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, *reinterpret_cast<const Base*>(this));
224  }
225  template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
226  size_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const {
227  return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, *reinterpret_cast<const Base*>(this));
228  }
229 };
230 
231 namespace internal {
232 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5>
233 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::size_t array_prod(const Sizes<V1, V2, V3, V4, V5>&) {
234  return Sizes<V1, V2, V3, V4, V5>::total_size;
235 }
236 }
237 
238 #endif
239 
240 // Boilerplate
241 namespace internal {
242 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor>
243 struct tensor_index_linearization_helper
244 {
245  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
246  Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const& dimensions)
247  {
248  return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) +
249  array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) *
250  tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
251  }
252 };
253 
254 template<typename Index, std::size_t NumIndices, bool RowMajor>
255 struct tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor>
256 {
257  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
258  Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const&)
259  {
260  return array_get<RowMajor ? 0 : NumIndices - 1>(indices);
261  }
262 };
263 } // end namespace internal
264 
265 
266 
267 // Dynamic size
268 template <typename DenseIndex, int NumDims>
269 struct DSizes : array<DenseIndex, NumDims> {
270  typedef array<DenseIndex, NumDims> Base;
271  static const int count = NumDims;
272 
273  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t rank() const {
274  return NumDims;
275  }
276 
277  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex TotalSize() const {
278  return internal::array_prod(*static_cast<const Base*>(this));
279  }
280 
281  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DSizes() {
282  for (int i = 0 ; i < NumDims; ++i) {
283  (*this)[i] = 0;
284  }
285  }
286  EIGEN_DEVICE_FUNC explicit DSizes(const array<DenseIndex, NumDims>& a) : Base(a) { }
287 
288 #ifdef EIGEN_HAS_VARIADIC_TEMPLATES
289  template<typename... IndexTypes> EIGEN_DEVICE_FUNC
290  EIGEN_STRONG_INLINE explicit DSizes(DenseIndex firstDimension, IndexTypes... otherDimensions) {
291  EIGEN_STATIC_ASSERT(sizeof...(otherDimensions) + 1 == NumDims, YOU_MADE_A_PROGRAMMING_MISTAKE)
292  (*this) = array<DenseIndex, NumDims>{{firstDimension, otherDimensions...}};
293  }
294 #else
295  EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0) {
296  eigen_assert(NumDims == 1);
297  (*this)[0] = i0;
298  }
299  EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0, const DenseIndex i1) {
300  eigen_assert(NumDims == 2);
301  (*this)[0] = i0;
302  (*this)[1] = i1;
303  }
304  EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2) {
305  eigen_assert(NumDims == 3);
306  (*this)[0] = i0;
307  (*this)[1] = i1;
308  (*this)[2] = i2;
309  }
310  EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3) {
311  eigen_assert(NumDims == 4);
312  (*this)[0] = i0;
313  (*this)[1] = i1;
314  (*this)[2] = i2;
315  (*this)[3] = i3;
316  }
317  EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3, const DenseIndex i4) {
318  eigen_assert(NumDims == 5);
319  (*this)[0] = i0;
320  (*this)[1] = i1;
321  (*this)[2] = i2;
322  (*this)[3] = i3;
323  (*this)[4] = i4;
324  }
325 #endif
326 
327  EIGEN_DEVICE_FUNC DSizes& operator = (const array<DenseIndex, NumDims>& other) {
328  *static_cast<Base*>(this) = other;
329  return *this;
330  }
331 
332  // A constexpr would be so much better here
333  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfColMajor(const array<DenseIndex, NumDims>& indices) const {
334  return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, false>::run(indices, *static_cast<const Base*>(this));
335  }
336  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfRowMajor(const array<DenseIndex, NumDims>& indices) const {
337  return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, true>::run(indices, *static_cast<const Base*>(this));
338  }
339 };
340 
341 
342 
343 
344 // Boilerplate
345 namespace internal {
346 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor>
347 struct tensor_vsize_index_linearization_helper
348 {
349  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
350  Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const& dimensions)
351  {
352  return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) +
353  array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) *
354  tensor_vsize_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
355  }
356 };
357 
358 template<typename Index, std::size_t NumIndices, bool RowMajor>
359 struct tensor_vsize_index_linearization_helper<Index, NumIndices, 0, RowMajor>
360 {
361  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
362  Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const&)
363  {
364  return array_get<RowMajor ? 0 : NumIndices - 1>(indices);
365  }
366 };
367 } // end namespace internal
368 
369 
370 namespace internal {
371 
372 template <typename DenseIndex, int NumDims> struct array_size<const DSizes<DenseIndex, NumDims> > {
373  static const size_t value = NumDims;
374 };
375 template <typename DenseIndex, int NumDims> struct array_size<DSizes<DenseIndex, NumDims> > {
376  static const size_t value = NumDims;
377 };
378 #ifndef EIGEN_EMULATE_CXX11_META_H
379 template <typename std::ptrdiff_t... Indices> struct array_size<const Sizes<Indices...> > {
380 static const std::ptrdiff_t value = Sizes<Indices...>::count;
381 };
382 template <typename std::ptrdiff_t... Indices> struct array_size<Sizes<Indices...> > {
383 static const std::ptrdiff_t value = Sizes<Indices...>::count;
384 };
385 template <std::ptrdiff_t n, typename std::ptrdiff_t... Indices> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<Indices...>&) {
386  return get<n, internal::numeric_list<std::size_t, Indices...> >::value;
387 }
388 template <std::ptrdiff_t n> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<>&) {
389  eigen_assert(false && "should never be called");
390  return -1;
391 }
392 #else
393 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> struct array_size<const Sizes<V1,V2,V3,V4,V5> > {
394  static const size_t value = Sizes<V1,V2,V3,V4,V5>::count;
395 };
396 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> struct array_size<Sizes<V1,V2,V3,V4,V5> > {
397  static const size_t value = Sizes<V1,V2,V3,V4,V5>::count;
398 };
399 template <std::size_t n, std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::size_t array_get(const Sizes<V1,V2,V3,V4,V5>&) {
400  return get<n, typename Sizes<V1,V2,V3,V4,V5>::Base>::value;
401 }
402 
403 #endif
404 
405 
406 template <typename Dims1, typename Dims2, size_t n, size_t m>
407 struct sizes_match_below_dim {
408  static inline bool run(Dims1&, Dims2&) {
409  return false;
410  }
411 };
412 template <typename Dims1, typename Dims2, size_t n>
413 struct sizes_match_below_dim<Dims1, Dims2, n, n> {
414  static inline bool run(Dims1& dims1, Dims2& dims2) {
415  return (array_get<n-1>(dims1) == array_get<n-1>(dims2)) &
416  sizes_match_below_dim<Dims1, Dims2, n-1, n-1>::run(dims1, dims2);
417  }
418 };
419 template <typename Dims1, typename Dims2>
420 struct sizes_match_below_dim<Dims1, Dims2, 0, 0> {
421  static inline bool run(Dims1&, Dims2&) {
422  return true;
423  }
424 };
425 
426 } // end namespace internal
427 
428 
429 template <typename Dims1, typename Dims2>
430 bool dimensions_match(Dims1& dims1, Dims2& dims2) {
431  return internal::sizes_match_below_dim<Dims1, Dims2, internal::array_size<Dims1>::value, internal::array_size<Dims2>::value>::run(dims1, dims2);
432 }
433 
434 } // end namespace Eigen
435 
436 #endif // EIGEN_CXX11_TENSOR_TENSOR_DIMENSIONS_H
Namespace containing all symbols from the Eigen library.
Definition: CXX11Meta.h:13