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