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