TensorIndexList.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_INDEX_LIST_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_INDEX_LIST_H
12 
13 #if defined(EIGEN_HAS_CONSTEXPR) && defined(EIGEN_HAS_VARIADIC_TEMPLATES)
14 
15 #define EIGEN_HAS_INDEX_LIST
16 
17 namespace Eigen {
18 
39 template <DenseIndex n>
40 struct type2index {
41  static const DenseIndex value = n;
42  constexpr operator DenseIndex() const { return n; }
43  void set(DenseIndex val) {
44  eigen_assert(val == n);
45  }
46 };
47 
48 namespace internal {
49 template <typename T>
50 void update_value(T& val, DenseIndex new_val) {
51  val = new_val;
52 }
53 template <DenseIndex n>
54 void update_value(type2index<n>& val, DenseIndex new_val) {
55  val.set(new_val);
56 }
57 
58 template <typename T>
59 struct is_compile_time_constant {
60  static constexpr bool value = false;
61 };
62 
63 template <DenseIndex idx>
64 struct is_compile_time_constant<type2index<idx> > {
65  static constexpr bool value = true;
66 };
67 template <DenseIndex idx>
68 struct is_compile_time_constant<const type2index<idx> > {
69  static constexpr bool value = true;
70 };
71 template <DenseIndex idx>
72 struct is_compile_time_constant<type2index<idx>& > {
73  static constexpr bool value = true;
74 };
75 template <DenseIndex idx>
76 struct is_compile_time_constant<const type2index<idx>& > {
77  static constexpr bool value = true;
78 };
79 
80 
81 
82 
83 template<typename... T>
84 struct IndexTuple;
85 
86 template<typename T, typename... O>
87 struct IndexTuple<T, O...> {
88  constexpr IndexTuple() : head(), others() { }
89  constexpr IndexTuple(const T& v, const O... o) : head(v), others(o...) { }
90 
91  constexpr static int count = 1 + sizeof...(O);
92  T head;
93  IndexTuple<O...> others;
94  typedef T Head;
95  typedef IndexTuple<O...> Other;
96 };
97 
98 template<typename T>
99  struct IndexTuple<T> {
100  constexpr IndexTuple() : head() { }
101  constexpr IndexTuple(const T& v) : head(v) { }
102 
103  constexpr static int count = 1;
104  T head;
105  typedef T Head;
106 };
107 
108 
109 template<int N, typename... T>
110 struct IndexTupleExtractor;
111 
112 template<int N, typename T, typename... O>
113 struct IndexTupleExtractor<N, T, O...> {
114 
115  typedef typename IndexTupleExtractor<N-1, O...>::ValType ValType;
116 
117  static constexpr ValType& get_val(IndexTuple<T, O...>& val) {
118  return IndexTupleExtractor<N-1, O...>::get_val(val.others);
119  }
120 
121  static constexpr const ValType& get_val(const IndexTuple<T, O...>& val) {
122  return IndexTupleExtractor<N-1, O...>::get_val(val.others);
123  }
124  template <typename V>
125  static void set_val(IndexTuple<T, O...>& val, V& new_val) {
126  IndexTupleExtractor<N-1, O...>::set_val(val.others, new_val);
127  }
128 
129 };
130 
131  template<typename T, typename... O>
132  struct IndexTupleExtractor<0, T, O...> {
133 
134  typedef T ValType;
135 
136  static constexpr ValType& get_val(IndexTuple<T, O...>& val) {
137  return val.head;
138  }
139  static constexpr const ValType& get_val(const IndexTuple<T, O...>& val) {
140  return val.head;
141  }
142  template <typename V>
143  static void set_val(IndexTuple<T, O...>& val, V& new_val) {
144  val.head = new_val;
145  }
146 };
147 
148 
149 
150 template <int N, typename T, typename... O>
151 constexpr typename IndexTupleExtractor<N, T, O...>::ValType& array_get(IndexTuple<T, O...>& tuple) {
152  return IndexTupleExtractor<N, T, O...>::get_val(tuple);
153 }
154 template <int N, typename T, typename... O>
155 constexpr const typename IndexTupleExtractor<N, T, O...>::ValType& array_get(const IndexTuple<T, O...>& tuple) {
156  return IndexTupleExtractor<N, T, O...>::get_val(tuple);
157 }
158 template <typename T, typename... O>
159  struct array_size<IndexTuple<T, O...> > {
160  static const size_t value = IndexTuple<T, O...>::count;
161 };
162 template <typename T, typename... O>
163  struct array_size<const IndexTuple<T, O...> > {
164  static const size_t value = IndexTuple<T, O...>::count;
165 };
166 
167 
168 
169 
170 template <DenseIndex Idx>
171 struct tuple_coeff {
172  template <typename... T>
173  static constexpr DenseIndex get(const DenseIndex i, const IndexTuple<T...>& t) {
174  return array_get<Idx>(t) * (i == Idx) + tuple_coeff<Idx-1>::get(i, t) * (i != Idx);
175  }
176  template <typename... T>
177  static void set(const DenseIndex i, IndexTuple<T...>& t, const DenseIndex value) {
178  if (i == Idx) {
179  update_value(array_get<Idx>(t), value);
180  } else {
181  tuple_coeff<Idx-1>::set(i, t, value);
182  }
183  }
184 
185  template <typename... T>
186  static constexpr bool value_known_statically(const DenseIndex i, const IndexTuple<T...>& t) {
187  return ((i == Idx) & is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value) ||
188  tuple_coeff<Idx-1>::value_known_statically(i, t);
189  }
190 
191  template <typename... T>
192  static constexpr bool values_up_to_known_statically(const IndexTuple<T...>& t) {
193  return is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
194  tuple_coeff<Idx-1>::values_up_to_known_statically(t);
195  }
196 
197  template <typename... T>
198  static constexpr bool values_up_to_statically_known_to_increase(const IndexTuple<T...>& t) {
199  return is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
200  is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
201  array_get<Idx>(t) > array_get<Idx-1>(t) &&
202  tuple_coeff<Idx-1>::values_up_to_statically_known_to_increase(t);
203  }
204 };
205 
206 template <>
207 struct tuple_coeff<0> {
208  template <typename... T>
209  static constexpr DenseIndex get(const DenseIndex i, const IndexTuple<T...>& t) {
210  // eigen_assert (i == 0); // gcc fails to compile assertions in constexpr
211  return array_get<0>(t) * (i == 0);
212  }
213  template <typename... T>
214  static void set(const DenseIndex i, IndexTuple<T...>& t, const DenseIndex value) {
215  eigen_assert (i == 0);
216  update_value(array_get<0>(t), value);
217  }
218  template <typename... T>
219  static constexpr bool value_known_statically(const DenseIndex i, const IndexTuple<T...>&) {
220  return is_compile_time_constant<typename IndexTupleExtractor<0, T...>::ValType>::value & (i == 0);
221  }
222 
223  template <typename... T>
224  static constexpr bool values_up_to_known_statically(const IndexTuple<T...>&) {
225  return is_compile_time_constant<typename IndexTupleExtractor<0, T...>::ValType>::value;
226  }
227 
228  template <typename... T>
229  static constexpr bool values_up_to_statically_known_to_increase(const IndexTuple<T...>&) {
230  return true;
231  }
232 };
233 } // namespace internal
234 
235 
236 
237 template<typename FirstType, typename... OtherTypes>
238  struct IndexList : internal::IndexTuple<FirstType, OtherTypes...> {
239  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr DenseIndex operator[] (const DenseIndex i) const {
240  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::get(i, *this);
241  }
242  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr DenseIndex get(const DenseIndex i) const {
243  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::get(i, *this);
244  }
245  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC void set(const DenseIndex i, const DenseIndex value) {
246  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::set(i, *this, value);
247  }
248 
249  constexpr IndexList(const internal::IndexTuple<FirstType, OtherTypes...>& other) : internal::IndexTuple<FirstType, OtherTypes...>(other) { }
250  constexpr IndexList(FirstType& first, OtherTypes... other) : internal::IndexTuple<FirstType, OtherTypes...>(first, other...) { }
251  constexpr IndexList() : internal::IndexTuple<FirstType, OtherTypes...>() { }
252 
253  constexpr bool value_known_statically(const DenseIndex i) const {
254  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::value_known_statically(i, *this);
255  }
256  constexpr bool all_values_known_statically() const {
257  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::values_up_to_known_statically(*this);
258  }
259 
260  constexpr bool values_statically_known_to_increase() const {
261  return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1>::values_up_to_statically_known_to_increase(*this);
262  }
263 };
264 
265 
266 template<typename FirstType, typename... OtherTypes>
267 constexpr IndexList<FirstType, OtherTypes...> make_index_list(FirstType val1, OtherTypes... other_vals) {
268  return IndexList<FirstType, OtherTypes...>(val1, other_vals...);
269 }
270 
271 
272 namespace internal {
273 
274 template<typename FirstType, typename... OtherTypes> size_t array_prod(const IndexList<FirstType, OtherTypes...>& sizes) {
275  size_t result = 1;
276  for (int i = 0; i < array_size<IndexList<FirstType, OtherTypes...> >::value; ++i) {
277  result *= sizes[i];
278  }
279  return result;
280 }
281 
282 template<typename FirstType, typename... OtherTypes> struct array_size<IndexList<FirstType, OtherTypes...> > {
283  static const size_t value = array_size<IndexTuple<FirstType, OtherTypes...> >::value;
284 };
285 template<typename FirstType, typename... OtherTypes> struct array_size<const IndexList<FirstType, OtherTypes...> > {
286  static const size_t value = array_size<IndexTuple<FirstType, OtherTypes...> >::value;
287 };
288 
289 template<DenseIndex N, typename FirstType, typename... OtherTypes> constexpr DenseIndex array_get(IndexList<FirstType, OtherTypes...>& a) {
290  return IndexTupleExtractor<N, FirstType, OtherTypes...>::get_val(a);
291 }
292 template<DenseIndex N, typename FirstType, typename... OtherTypes> constexpr DenseIndex array_get(const IndexList<FirstType, OtherTypes...>& a) {
293  return IndexTupleExtractor<N, FirstType, OtherTypes...>::get_val(a);
294 }
295 
296 template <typename T>
297 struct index_known_statically_impl {
298  static constexpr bool run(const DenseIndex) {
299  return false;
300  }
301 };
302 
303 template <typename FirstType, typename... OtherTypes>
304 struct index_known_statically_impl<IndexList<FirstType, OtherTypes...> > {
305  static constexpr bool run(const DenseIndex i) {
306  return IndexList<FirstType, OtherTypes...>().value_known_statically(i);
307  }
308 };
309 
310 template <typename FirstType, typename... OtherTypes>
311 struct index_known_statically_impl<const IndexList<FirstType, OtherTypes...> > {
312  static constexpr bool run(const DenseIndex i) {
313  return IndexList<FirstType, OtherTypes...>().value_known_statically(i);
314  }
315 };
316 
317 
318 template <typename T>
319 struct all_indices_known_statically_impl {
320  static constexpr bool run() {
321  return false;
322  }
323 };
324 
325 template <typename FirstType, typename... OtherTypes>
326 struct all_indices_known_statically_impl<IndexList<FirstType, OtherTypes...> > {
327  static constexpr bool run() {
328  return IndexList<FirstType, OtherTypes...>().all_values_known_statically();
329  }
330 };
331 
332 template <typename FirstType, typename... OtherTypes>
333 struct all_indices_known_statically_impl<const IndexList<FirstType, OtherTypes...> > {
334  static constexpr bool run() {
335  return IndexList<FirstType, OtherTypes...>().all_values_known_statically();
336  }
337 };
338 
339 
340 template <typename T>
341 struct indices_statically_known_to_increase_impl {
342  static constexpr bool run() {
343  return false;
344  }
345 };
346 
347 template <typename FirstType, typename... OtherTypes>
348  struct indices_statically_known_to_increase_impl<IndexList<FirstType, OtherTypes...> > {
349  static constexpr bool run() {
350  return Eigen::IndexList<FirstType, OtherTypes...>().values_statically_known_to_increase();
351  }
352 };
353 
354 template <typename FirstType, typename... OtherTypes>
355  struct indices_statically_known_to_increase_impl<const IndexList<FirstType, OtherTypes...> > {
356  static constexpr bool run() {
357  return Eigen::IndexList<FirstType, OtherTypes...>().values_statically_known_to_increase();
358  }
359 };
360 
361 
362 template <typename Tx>
363 struct index_statically_eq_impl {
364  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
365  return false;
366  }
367 };
368 
369 template <typename FirstType, typename... OtherTypes>
370 struct index_statically_eq_impl<IndexList<FirstType, OtherTypes...> > {
371  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
372  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
373  (IndexList<FirstType, OtherTypes...>().get(i) == value);
374  }
375 };
376 
377 template <typename FirstType, typename... OtherTypes>
378 struct index_statically_eq_impl<const IndexList<FirstType, OtherTypes...> > {
379  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
380  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
381  (IndexList<FirstType, OtherTypes...>().get(i) == value);
382  }
383 };
384 
385 
386 template <typename T>
387 struct index_statically_ne_impl {
388  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
389  return false;
390  }
391 };
392 
393 template <typename FirstType, typename... OtherTypes>
394 struct index_statically_ne_impl<IndexList<FirstType, OtherTypes...> > {
395  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
396  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
397  (IndexList<FirstType, OtherTypes...>().get(i) != value);
398  }
399 };
400 
401 template <typename FirstType, typename... OtherTypes>
402 struct index_statically_ne_impl<const IndexList<FirstType, OtherTypes...> > {
403  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
404  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
405  (IndexList<FirstType, OtherTypes...>().get(i) != value);
406  }
407 };
408 
409 
410 template <typename T>
411 struct index_statically_gt_impl {
412  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
413  return false;
414  }
415 };
416 
417 template <typename FirstType, typename... OtherTypes>
418 struct index_statically_gt_impl<IndexList<FirstType, OtherTypes...> > {
419  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
420  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
421  (IndexList<FirstType, OtherTypes...>().get(i) > value);
422  }
423 };
424 
425 template <typename FirstType, typename... OtherTypes>
426 struct index_statically_gt_impl<const IndexList<FirstType, OtherTypes...> > {
427  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
428  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
429  (IndexList<FirstType, OtherTypes...>().get(i) > value);
430  }
431 };
432 
433 
434 
435 template <typename T>
436 struct index_statically_lt_impl {
437  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
438  return false;
439  }
440 };
441 
442 template <typename FirstType, typename... OtherTypes>
443 struct index_statically_lt_impl<IndexList<FirstType, OtherTypes...> > {
444  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
445  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
446  (IndexList<FirstType, OtherTypes...>().get(i) < value);
447  }
448 };
449 
450 template <typename FirstType, typename... OtherTypes>
451 struct index_statically_lt_impl<const IndexList<FirstType, OtherTypes...> > {
452  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
453  return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
454  (IndexList<FirstType, OtherTypes...>().get(i) < value);
455  }
456 };
457 
458 } // end namespace internal
459 } // end namespace Eigen
460 
461 #else
462 
463 namespace Eigen {
464 namespace internal {
465 
466 template <typename T>
467 struct index_known_statically_impl {
468  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run(const DenseIndex) {
469  return false;
470  }
471 };
472 
473 template <typename T>
474 struct all_indices_known_statically_impl {
475  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run() {
476  return false;
477  }
478 };
479 
480 template <typename T>
481 struct indices_statically_known_to_increase_impl {
482  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run() {
483  return false;
484  }
485 };
486 
487 template <typename T>
488 struct index_statically_eq_impl {
489  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run(DenseIndex, DenseIndex) {
490  return false;
491  }
492 };
493 
494 template <typename T>
495 struct index_statically_ne_impl {
496  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run(DenseIndex, DenseIndex) {
497  return false;
498  }
499 };
500 
501 template <typename T>
502 struct index_statically_gt_impl {
503  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run(DenseIndex, DenseIndex) {
504  return false;
505  }
506 };
507 
508 template <typename T>
509 struct index_statically_lt_impl {
510  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static bool run(DenseIndex, DenseIndex) {
511  return false;
512  }
513 };
514 
515 } // end namespace internal
516 } // end namespace Eigen
517 
518 #endif
519 
520 
521 namespace Eigen {
522 namespace internal {
523 template <typename T>
524 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_known_statically(DenseIndex i) {
525  return index_known_statically_impl<T>::run(i);
526 }
527 
528 template <typename T>
529 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool all_indices_known_statically() {
530  return all_indices_known_statically_impl<T>::run();
531 }
532 
533 template <typename T>
534 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool indices_statically_known_to_increase() {
535  return indices_statically_known_to_increase_impl<T>::run();
536 }
537 
538 template <typename T>
539 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_eq(DenseIndex i, DenseIndex value) {
540  return index_statically_eq_impl<T>::run(i, value);
541 }
542 
543 template <typename T>
544 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_ne(DenseIndex i, DenseIndex value) {
545  return index_statically_ne_impl<T>::run(i, value);
546 }
547 
548 template <typename T>
549 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_gt(DenseIndex i, DenseIndex value) {
550  return index_statically_gt_impl<T>::run(i, value);
551 }
552 
553 template <typename T>
554 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_lt(DenseIndex i, DenseIndex value) {
555  return index_statically_lt_impl<T>::run(i, value);
556 }
557 
558 } // end namespace internal
559 } // end namespace Eigen
560 
561 
562 #endif // EIGEN_CXX11_TENSOR_TENSOR_INDEX_LIST_H
Namespace containing all symbols from the Eigen library.
Definition: CXX11Meta.h:13