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