Eigen-unsupported  3.4.1 (git rev 28ded8800c26864e537852658428ab44c8399e87)
 
Loading...
Searching...
No Matches
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
14namespace Eigen {
15
16// Boilerplate code
17namespace internal {
18
19template<std::ptrdiff_t n, typename Dimension> struct dget {
20 static const std::ptrdiff_t value = get<n, Dimension>::value;
21};
22
23
24template<typename Index, std::ptrdiff_t NumIndices, std::ptrdiff_t n, bool RowMajor>
25struct fixed_size_tensor_index_linearization_helper
26{
27 template <typename Dimensions> EIGEN_DEVICE_FUNC
28 static EIGEN_STRONG_INLINE Index run(array<Index, NumIndices> const& indices,
29 const Dimensions& dimensions)
30 {
31 return array_get<RowMajor ? n - 1 : (NumIndices - n)>(indices) +
32 dget<RowMajor ? n - 1 : (NumIndices - n), Dimensions>::value *
33 fixed_size_tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
34 }
35};
36
37template<typename Index, std::ptrdiff_t NumIndices, bool RowMajor>
38struct fixed_size_tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor>
39{
40 template <typename Dimensions> EIGEN_DEVICE_FUNC
41 static EIGEN_STRONG_INLINE Index run(array<Index, NumIndices> const&, const Dimensions&)
42 {
43 return 0;
44 }
45};
46
47template<typename Index, std::ptrdiff_t n>
48struct fixed_size_tensor_index_extraction_helper
49{
50 template <typename Dimensions> EIGEN_DEVICE_FUNC
51 static EIGEN_STRONG_INLINE Index run(const Index index,
52 const Dimensions& dimensions)
53 {
54 const Index mult = (index == n-1) ? 1 : 0;
55 return array_get<n-1>(dimensions) * mult +
56 fixed_size_tensor_index_extraction_helper<Index, n - 1>::run(index, dimensions);
57 }
58};
59
60template<typename Index>
61struct fixed_size_tensor_index_extraction_helper<Index, 0>
62{
63 template <typename Dimensions> EIGEN_DEVICE_FUNC
64 static EIGEN_STRONG_INLINE Index run(const Index,
65 const Dimensions&)
66 {
67 return 0;
68 }
69 };
70
71} // end namespace internal
72
73
74#ifndef EIGEN_EMULATE_CXX11_META_H
87template <typename std::ptrdiff_t... Indices>
88struct Sizes {
89 typedef internal::numeric_list<std::ptrdiff_t, Indices...> Base;
90 const Base t = Base();
91 static const std::ptrdiff_t total_size = internal::arg_prod(Indices...);
92 static const ptrdiff_t count = Base::count;
93
94 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t rank() const {
95 return Base::count;
96 }
97
98 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t TotalSize() {
99 return internal::arg_prod(Indices...);
100 }
101
102 EIGEN_DEVICE_FUNC Sizes() { }
103 template <typename DenseIndex>
104 explicit EIGEN_DEVICE_FUNC Sizes(const array<DenseIndex, Base::count>& /*indices*/) {
105 // todo: add assertion
106 }
107#if EIGEN_HAS_VARIADIC_TEMPLATES
108 template <typename... DenseIndex> EIGEN_DEVICE_FUNC Sizes(DenseIndex...) { }
109 explicit EIGEN_DEVICE_FUNC Sizes(std::initializer_list<std::ptrdiff_t> /*l*/) {
110 // todo: add assertion
111 }
112#endif
113
114 template <typename T> Sizes& operator = (const T& /*other*/) {
115 // add assertion failure if the size of other is different
116 return *this;
117 }
118
119 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t operator[] (const std::ptrdiff_t index) const {
120 return internal::fixed_size_tensor_index_extraction_helper<std::ptrdiff_t, Base::count>::run(index, t);
121 }
122
123 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
124 ptrdiff_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const {
125 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, t);
126 }
127 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
128 ptrdiff_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const {
129 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, t);
130 }
131};
132
133namespace internal {
134template <typename std::ptrdiff_t... Indices>
135EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_prod(const Sizes<Indices...>&) {
136 return Sizes<Indices...>::total_size;
137}
138}
139
140#else
141
142template <std::ptrdiff_t n>
143struct non_zero_size {
144 typedef internal::type2val<std::ptrdiff_t, n> type;
145};
146template <>
147struct non_zero_size<0> {
148 typedef internal::null_type type;
149};
150
151template <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 {
152 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;
153 static const std::ptrdiff_t count = Base::count;
154 static const std::ptrdiff_t total_size = internal::arg_prod<Base>::value;
155
156 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ptrdiff_t rank() const {
157 return count;
158 }
159
160 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ptrdiff_t TotalSize() {
161 return internal::arg_prod<Base>::value;
162 }
163
164 Sizes() { }
165 template <typename DenseIndex>
166 explicit Sizes(const array<DenseIndex, Base::count>& /*indices*/) {
167 // todo: add assertion
168 }
169 template <typename T> Sizes& operator = (const T& /*other*/) {
170 // add assertion failure if the size of other is different
171 return *this;
172 }
173
174#if EIGEN_HAS_VARIADIC_TEMPLATES
175 template <typename... DenseIndex> Sizes(DenseIndex... /*indices*/) { }
176 explicit Sizes(std::initializer_list<std::ptrdiff_t>) {
177 // todo: add assertion
178 }
179#else
180 EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex) {
181 }
182 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex) {
183 }
184 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex) {
185 }
186 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) {
187 }
188 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) {
189 }
190#endif
191
192 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index operator[] (const Index index) const {
193 switch (index) {
194 case 0:
195 return internal::get<0, Base>::value;
196 case 1:
197 return internal::get<1, Base>::value;
198 case 2:
199 return internal::get<2, Base>::value;
200 case 3:
201 return internal::get<3, Base>::value;
202 case 4:
203 return internal::get<4, Base>::value;
204 default:
205 eigen_assert(false && "index overflow");
206 return static_cast<Index>(-1);
207 }
208 }
209
210 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
211 ptrdiff_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const {
212 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, *reinterpret_cast<const Base*>(this));
213 }
214 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
215 ptrdiff_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const {
216 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, *reinterpret_cast<const Base*>(this));
217 }
218};
219
220namespace internal {
221template <std::ptrdiff_t V1, std::ptrdiff_t V2, std::ptrdiff_t V3, std::ptrdiff_t V4, std::ptrdiff_t V5>
222EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_prod(const Sizes<V1, V2, V3, V4, V5>&) {
223 return Sizes<V1, V2, V3, V4, V5>::total_size;
224}
225}
226
227#endif
228
229// Boilerplate
230namespace internal {
231template<typename Index, std::ptrdiff_t NumIndices, std::ptrdiff_t n, bool RowMajor>
232struct tensor_index_linearization_helper
233{
234 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
235 Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const& dimensions)
236 {
237 return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) +
238 array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) *
239 tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
240 }
241};
242
243template<typename Index, std::ptrdiff_t NumIndices, bool RowMajor>
244struct tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor>
245{
246 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
247 Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const&)
248 {
249 return array_get<RowMajor ? 0 : NumIndices - 1>(indices);
250 }
251};
252} // end namespace internal
253
265template <typename DenseIndex, int NumDims>
266struct DSizes : array<DenseIndex, NumDims> {
267 typedef array<DenseIndex, NumDims> Base;
268 static const int count = NumDims;
269
270 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rank() const {
271 return NumDims;
272 }
273
274 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex TotalSize() const {
275 return (NumDims == 0) ? 1 : internal::array_prod(*static_cast<const Base*>(this));
276 }
277
278 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DSizes() {
279 for (int i = 0 ; i < NumDims; ++i) {
280 (*this)[i] = 0;
281 }
282 }
283 EIGEN_DEVICE_FUNC explicit DSizes(const array<DenseIndex, NumDims>& a) : Base(a) { }
284
285 EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0) {
286 eigen_assert(NumDims == 1);
287 (*this)[0] = i0;
288 }
289
290 EIGEN_DEVICE_FUNC DSizes(const DimensionList<DenseIndex, NumDims>& a) {
291 for (int i = 0 ; i < NumDims; ++i) {
292 (*this)[i] = a[i];
293 }
294 }
295
296 // Enable DSizes index type promotion only if we are promoting to the
297 // larger type, e.g. allow to promote dimensions of type int to long.
298 template<typename OtherIndex>
299 EIGEN_DEVICE_FUNC
300 explicit DSizes(const array<OtherIndex, NumDims>& other,
301 // Default template parameters require c++11.
302 typename internal::enable_if<
303 internal::is_same<
304 DenseIndex,
305 typename internal::promote_index_type<
306 DenseIndex,
307 OtherIndex
308 >::type
309 >::value, void*>::type = 0) {
310 for (int i = 0; i < NumDims; ++i) {
311 (*this)[i] = static_cast<DenseIndex>(other[i]);
312 }
313 }
314
315#ifdef EIGEN_HAS_INDEX_LIST
316 template <typename FirstType, typename... OtherTypes>
317 EIGEN_DEVICE_FUNC
318 explicit DSizes(const Eigen::IndexList<FirstType, OtherTypes...>& dimensions) {
319 for (int i = 0; i < dimensions.count; ++i) {
320 (*this)[i] = dimensions[i];
321 }
322 }
323#endif
324
325#ifndef EIGEN_EMULATE_CXX11_META_H
326 template <typename std::ptrdiff_t... Indices>
327 EIGEN_DEVICE_FUNC DSizes(const Sizes<Indices...>& a) {
328 for (int i = 0 ; i < NumDims; ++i) {
329 (*this)[i] = a[i];
330 }
331 }
332#else
333 template <std::ptrdiff_t V1, std::ptrdiff_t V2, std::ptrdiff_t V3, std::ptrdiff_t V4, std::ptrdiff_t V5>
334 EIGEN_DEVICE_FUNC DSizes(const Sizes<V1, V2, V3, V4, V5>& a) {
335 for (int i = 0 ; i < NumDims; ++i) {
336 (*this)[i] = a[i];
337 }
338 }
339#endif
340
341#if EIGEN_HAS_VARIADIC_TEMPLATES
342 template<typename... IndexTypes> EIGEN_DEVICE_FUNC
343 EIGEN_STRONG_INLINE explicit DSizes(DenseIndex firstDimension, DenseIndex secondDimension, IndexTypes... otherDimensions) : Base({{firstDimension, secondDimension, otherDimensions...}}) {
344 EIGEN_STATIC_ASSERT(sizeof...(otherDimensions) + 2 == NumDims, YOU_MADE_A_PROGRAMMING_MISTAKE)
345 }
346#else
347 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1) {
348 eigen_assert(NumDims == 2);
349 (*this)[0] = i0;
350 (*this)[1] = i1;
351 }
352 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2) {
353 eigen_assert(NumDims == 3);
354 (*this)[0] = i0;
355 (*this)[1] = i1;
356 (*this)[2] = i2;
357 }
358 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3) {
359 eigen_assert(NumDims == 4);
360 (*this)[0] = i0;
361 (*this)[1] = i1;
362 (*this)[2] = i2;
363 (*this)[3] = i3;
364 }
365 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3, const DenseIndex i4) {
366 eigen_assert(NumDims == 5);
367 (*this)[0] = i0;
368 (*this)[1] = i1;
369 (*this)[2] = i2;
370 (*this)[3] = i3;
371 (*this)[4] = i4;
372 }
373#endif
374
375 EIGEN_DEVICE_FUNC DSizes& operator = (const array<DenseIndex, NumDims>& other) {
376 *static_cast<Base*>(this) = other;
377 return *this;
378 }
379
380 // A constexpr would be so much better here
381 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfColMajor(const array<DenseIndex, NumDims>& indices) const {
382 return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, false>::run(indices, *static_cast<const Base*>(this));
383 }
384 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfRowMajor(const array<DenseIndex, NumDims>& indices) const {
385 return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, true>::run(indices, *static_cast<const Base*>(this));
386 }
387};
388
389template <typename IndexType, int NumDims>
390std::ostream& operator<<(std::ostream& os,
391 const DSizes<IndexType, NumDims>& dims) {
392 os << "[";
393 for (int i = 0; i < NumDims; ++i) {
394 if (i > 0) os << ", ";
395 os << dims[i];
396 }
397 os << "]";
398 return os;
399}
400
401// Boilerplate
402namespace internal {
403template<typename Index, std::ptrdiff_t NumIndices, std::ptrdiff_t n, bool RowMajor>
404struct tensor_vsize_index_linearization_helper
405{
406 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
407 Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const& dimensions)
408 {
409 return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) +
410 array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) *
411 tensor_vsize_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions);
412 }
413};
414
415template<typename Index, std::ptrdiff_t NumIndices, bool RowMajor>
416struct tensor_vsize_index_linearization_helper<Index, NumIndices, 0, RowMajor>
417{
418 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
419 Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const&)
420 {
421 return array_get<RowMajor ? 0 : NumIndices - 1>(indices);
422 }
423};
424} // end namespace internal
425
426
427namespace internal {
428
429template <typename DenseIndex, int NumDims> struct array_size<const DSizes<DenseIndex, NumDims> > {
430 static const ptrdiff_t value = NumDims;
431};
432template <typename DenseIndex, int NumDims> struct array_size<DSizes<DenseIndex, NumDims> > {
433 static const ptrdiff_t value = NumDims;
434};
435#ifndef EIGEN_EMULATE_CXX11_META_H
436template <typename std::ptrdiff_t... Indices> struct array_size<const Sizes<Indices...> > {
437static const std::ptrdiff_t value = Sizes<Indices...>::count;
438};
439template <typename std::ptrdiff_t... Indices> struct array_size<Sizes<Indices...> > {
440static const std::ptrdiff_t value = Sizes<Indices...>::count;
441};
442template <std::ptrdiff_t n, typename std::ptrdiff_t... Indices> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<Indices...>&) {
443 return get<n, internal::numeric_list<std::ptrdiff_t, Indices...> >::value;
444}
445template <std::ptrdiff_t n> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<>&) {
446 eigen_assert(false && "should never be called");
447 return -1;
448}
449#else
450template <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> > {
451 static const ptrdiff_t value = Sizes<V1,V2,V3,V4,V5>::count;
452};
453template <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> > {
454 static const ptrdiff_t value = Sizes<V1,V2,V3,V4,V5>::count;
455};
456template <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>&) {
457 return get<n, typename Sizes<V1,V2,V3,V4,V5>::Base>::value;
458}
459
460#endif
461
462
463template <typename Dims1, typename Dims2, ptrdiff_t n, ptrdiff_t m>
464struct sizes_match_below_dim {
465 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(Dims1&, Dims2&) {
466 return false;
467 }
468};
469template <typename Dims1, typename Dims2, ptrdiff_t n>
470struct sizes_match_below_dim<Dims1, Dims2, n, n> {
471 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(Dims1& dims1, Dims2& dims2) {
472 return (array_get<n-1>(dims1) == array_get<n-1>(dims2)) &&
473 sizes_match_below_dim<Dims1, Dims2, n-1, n-1>::run(dims1, dims2);
474 }
475};
476template <typename Dims1, typename Dims2>
477struct sizes_match_below_dim<Dims1, Dims2, 0, 0> {
478 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(Dims1&, Dims2&) {
479 return true;
480 }
481};
482
483} // end namespace internal
484
485
486template <typename Dims1, typename Dims2>
487EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool dimensions_match(Dims1 dims1, Dims2 dims2) {
488 return internal::sizes_match_below_dim<Dims1, Dims2, internal::array_size<Dims1>::value, internal::array_size<Dims2>::value>::run(dims1, dims2);
489}
490
491} // end namespace Eigen
492
493#endif // EIGEN_CXX11_TENSOR_TENSOR_DIMENSIONS_H
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index