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
14#if EIGEN_HAS_CONSTEXPR && EIGEN_HAS_VARIADIC_TEMPLATES
15
16#define EIGEN_HAS_INDEX_LIST
17
18namespace Eigen {
19
20/** \internal
21  *
22  * \class TensorIndexList
23  * \ingroup CXX11_Tensor_Module
24  *
25  * \brief Set of classes used to encode a set of Tensor dimensions/indices.
26  *
27  * The indices in the list can be known at compile time or at runtime. A mix
28  * of static and dynamic indices can also be provided if needed. The tensor
29  * code will attempt to take advantage of the indices that are known at
30  * compile time to optimize the code it generates.
31  *
32  * This functionality requires a c++11 compliant compiler. If your compiler
33  * is older you need to use arrays of indices instead.
34  *
35  * Several examples are provided in the cxx11_tensor_index_list.cpp file.
36  *
37  * \sa Tensor
38  */
39
40template <DenseIndex n>
41struct type2index {
42  static const DenseIndex value = n;
43  EIGEN_DEVICE_FUNC constexpr operator DenseIndex() const { return n; }
44  EIGEN_DEVICE_FUNC void set(DenseIndex val) {
45    eigen_assert(val == n);
46  }
47};
48
49// This can be used with IndexPairList to get compile-time constant pairs,
50// such as IndexPairList<type2indexpair<1,2>, type2indexpair<3,4>>().
51template <DenseIndex f, DenseIndex s>
52struct type2indexpair {
53  static const DenseIndex first = f;
54  static const DenseIndex second = s;
55
56  constexpr EIGEN_DEVICE_FUNC operator IndexPair<DenseIndex>() const {
57    return IndexPair<DenseIndex>(f, s);
58  }
59
60  EIGEN_DEVICE_FUNC void set(const IndexPair<DenseIndex>& val) {
61    eigen_assert(val.first == f);
62    eigen_assert(val.second == s);
63  }
64};
65
66
67template<DenseIndex n> struct NumTraits<type2index<n> >
68{
69  typedef DenseIndex Real;
70  enum {
71    IsComplex = 0,
72    RequireInitialization = false,
73    ReadCost = 1,
74    AddCost = 1,
75    MulCost = 1
76  };
77
78  EIGEN_DEVICE_FUNC static inline Real epsilon() { return 0; }
79  EIGEN_DEVICE_FUNC static inline Real dummy_precision() { return 0; }
80  EIGEN_DEVICE_FUNC static inline Real highest() { return n; }
81  EIGEN_DEVICE_FUNC static inline Real lowest() { return n; }
82};
83
84namespace internal {
85template <typename T>
86EIGEN_DEVICE_FUNC void update_value(T& val, DenseIndex new_val) {
87  val = new_val;
88}
89template <DenseIndex n>
90EIGEN_DEVICE_FUNC void update_value(type2index<n>& val, DenseIndex new_val) {
91  val.set(new_val);
92}
93
94template <typename T>
95EIGEN_DEVICE_FUNC void update_value(T& val, IndexPair<DenseIndex> new_val) {
96  val = new_val;
97}
98template <DenseIndex f, DenseIndex s>
99EIGEN_DEVICE_FUNC void update_value(type2indexpair<f, s>& val, IndexPair<DenseIndex> new_val) {
100  val.set(new_val);
101}
102
103
104template <typename T>
105struct is_compile_time_constant {
106  static constexpr bool value = false;
107};
108
109template <DenseIndex idx>
110struct is_compile_time_constant<type2index<idx> > {
111  static constexpr bool value = true;
112};
113template <DenseIndex idx>
114struct is_compile_time_constant<const type2index<idx> > {
115  static constexpr bool value = true;
116};
117template <DenseIndex idx>
118struct is_compile_time_constant<type2index<idx>& > {
119  static constexpr bool value = true;
120};
121template <DenseIndex idx>
122struct is_compile_time_constant<const type2index<idx>& > {
123  static constexpr bool value = true;
124};
125
126template <DenseIndex f, DenseIndex s>
127struct is_compile_time_constant<type2indexpair<f, s> > {
128  static constexpr bool value = true;
129};
130template <DenseIndex f, DenseIndex s>
131struct is_compile_time_constant<const type2indexpair<f, s> > {
132  static constexpr bool value = true;
133};
134template <DenseIndex f, DenseIndex s>
135struct is_compile_time_constant<type2indexpair<f, s>& > {
136  static constexpr bool value = true;
137};
138template <DenseIndex f, DenseIndex s>
139struct is_compile_time_constant<const type2indexpair<f, s>& > {
140  static constexpr bool value = true;
141};
142
143
144template<typename... T>
145struct IndexTuple;
146
147template<typename T, typename... O>
148struct IndexTuple<T, O...> {
149  EIGEN_DEVICE_FUNC constexpr IndexTuple() : head(), others() { }
150  EIGEN_DEVICE_FUNC constexpr IndexTuple(const T& v, const O... o) : head(v), others(o...) { }
151
152  constexpr static int count = 1 + sizeof...(O);
153  T head;
154  IndexTuple<O...> others;
155  typedef T Head;
156  typedef IndexTuple<O...> Other;
157};
158
159template<typename T>
160  struct IndexTuple<T> {
161  EIGEN_DEVICE_FUNC constexpr IndexTuple() : head() { }
162  EIGEN_DEVICE_FUNC constexpr IndexTuple(const T& v) : head(v) { }
163
164  constexpr static int count = 1;
165  T head;
166  typedef T Head;
167};
168
169
170template<int N, typename... T>
171struct IndexTupleExtractor;
172
173template<int N, typename T, typename... O>
174struct IndexTupleExtractor<N, T, O...> {
175
176  typedef typename IndexTupleExtractor<N-1, O...>::ValType ValType;
177
178  EIGEN_DEVICE_FUNC static constexpr ValType& get_val(IndexTuple<T, O...>& val) {
179    return IndexTupleExtractor<N-1, O...>::get_val(val.others);
180  }
181
182  EIGEN_DEVICE_FUNC static constexpr const ValType& get_val(const IndexTuple<T, O...>& val) {
183    return IndexTupleExtractor<N-1, O...>::get_val(val.others);
184  }
185  template <typename V>
186  EIGEN_DEVICE_FUNC static void set_val(IndexTuple<T, O...>& val, V& new_val) {
187    IndexTupleExtractor<N-1, O...>::set_val(val.others, new_val);
188  }
189
190};
191
192template<typename T, typename... O>
193  struct IndexTupleExtractor<0, T, O...> {
194
195  typedef T ValType;
196
197  EIGEN_DEVICE_FUNC static constexpr ValType& get_val(IndexTuple<T, O...>& val) {
198    return val.head;
199  }
200  EIGEN_DEVICE_FUNC static constexpr const ValType& get_val(const IndexTuple<T, O...>& val) {
201    return val.head;
202  }
203  template <typename V>
204  EIGEN_DEVICE_FUNC static void set_val(IndexTuple<T, O...>& val, V& new_val) {
205    val.head = new_val;
206  }
207};
208
209
210
211template <int N, typename T, typename... O>
212EIGEN_DEVICE_FUNC constexpr typename IndexTupleExtractor<N, T, O...>::ValType& array_get(IndexTuple<T, O...>& tuple) {
213  return IndexTupleExtractor<N, T, O...>::get_val(tuple);
214}
215template <int N, typename T, typename... O>
216EIGEN_DEVICE_FUNC constexpr const typename IndexTupleExtractor<N, T, O...>::ValType& array_get(const IndexTuple<T, O...>& tuple) {
217  return IndexTupleExtractor<N, T, O...>::get_val(tuple);
218}
219template <typename T, typename... O>
220  struct array_size<IndexTuple<T, O...> > {
221  static const size_t value = IndexTuple<T, O...>::count;
222};
223template <typename T, typename... O>
224  struct array_size<const IndexTuple<T, O...> > {
225  static const size_t value = IndexTuple<T, O...>::count;
226};
227
228
229
230
231template <DenseIndex Idx, typename ValueT>
232struct tuple_coeff {
233  template <typename... T>
234  EIGEN_DEVICE_FUNC static constexpr ValueT get(const DenseIndex i, const IndexTuple<T...>& t) {
235    //    return array_get<Idx>(t) * (i == Idx) + tuple_coeff<Idx-1>::get(i, t) * (i != Idx);
236    return (i == Idx ? array_get<Idx>(t) : tuple_coeff<Idx-1, ValueT>::get(i, t));
237  }
238  template <typename... T>
239  EIGEN_DEVICE_FUNC static void set(const DenseIndex i, IndexTuple<T...>& t, const ValueT& value) {
240    if (i == Idx) {
241      update_value(array_get<Idx>(t), value);
242    } else {
243      tuple_coeff<Idx-1, ValueT>::set(i, t, value);
244    }
245  }
246
247  template <typename... T>
248  EIGEN_DEVICE_FUNC static constexpr bool value_known_statically(const DenseIndex i, const IndexTuple<T...>& t) {
249    return ((i == Idx) & is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value) ||
250        tuple_coeff<Idx-1, ValueT>::value_known_statically(i, t);
251  }
252
253  template <typename... T>
254  EIGEN_DEVICE_FUNC static constexpr bool values_up_to_known_statically(const IndexTuple<T...>& t) {
255    return is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
256        tuple_coeff<Idx-1, ValueT>::values_up_to_known_statically(t);
257  }
258
259  template <typename... T>
260  EIGEN_DEVICE_FUNC static constexpr bool values_up_to_statically_known_to_increase(const IndexTuple<T...>& t) {
261    return is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
262           is_compile_time_constant<typename IndexTupleExtractor<Idx, T...>::ValType>::value &&
263           array_get<Idx>(t) > array_get<Idx-1>(t) &&
264           tuple_coeff<Idx-1, ValueT>::values_up_to_statically_known_to_increase(t);
265  }
266};
267
268template <typename ValueT>
269struct tuple_coeff<0, ValueT> {
270  template <typename... T>
271  EIGEN_DEVICE_FUNC static constexpr ValueT get(const DenseIndex /*i*/, const IndexTuple<T...>& t) {
272    //  eigen_assert (i == 0);  // gcc fails to compile assertions in constexpr
273    return array_get<0>(t)/* * (i == 0)*/;
274  }
275  template <typename... T>
276  EIGEN_DEVICE_FUNC static void set(const DenseIndex i, IndexTuple<T...>& t, const ValueT value) {
277    eigen_assert (i == 0);
278    update_value(array_get<0>(t), value);
279  }
280  template <typename... T>
281  EIGEN_DEVICE_FUNC static constexpr bool value_known_statically(const DenseIndex i, const IndexTuple<T...>&) {
282    return is_compile_time_constant<typename IndexTupleExtractor<0, T...>::ValType>::value & (i == 0);
283  }
284
285  template <typename... T>
286  EIGEN_DEVICE_FUNC static constexpr bool values_up_to_known_statically(const IndexTuple<T...>&) {
287    return is_compile_time_constant<typename IndexTupleExtractor<0, T...>::ValType>::value;
288  }
289
290  template <typename... T>
291  EIGEN_DEVICE_FUNC static constexpr bool values_up_to_statically_known_to_increase(const IndexTuple<T...>&) {
292    return true;
293  }
294};
295}  // namespace internal
296
297
298
299template<typename FirstType, typename... OtherTypes>
300struct IndexList : internal::IndexTuple<FirstType, OtherTypes...> {
301  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr DenseIndex operator[] (const DenseIndex i) const {
302    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::get(i, *this);
303  }
304  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr DenseIndex get(const DenseIndex i) const {
305    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::get(i, *this);
306  }
307  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC void set(const DenseIndex i, const DenseIndex value) {
308    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::set(i, *this, value);
309  }
310
311  EIGEN_DEVICE_FUNC constexpr IndexList(const internal::IndexTuple<FirstType, OtherTypes...>& other) : internal::IndexTuple<FirstType, OtherTypes...>(other) { }
312  EIGEN_DEVICE_FUNC constexpr IndexList(FirstType& first, OtherTypes... other) : internal::IndexTuple<FirstType, OtherTypes...>(first, other...) { }
313  EIGEN_DEVICE_FUNC constexpr IndexList() : internal::IndexTuple<FirstType, OtherTypes...>() { }
314
315  EIGEN_DEVICE_FUNC constexpr bool value_known_statically(const DenseIndex i) const {
316    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::value_known_statically(i, *this);
317  }
318  EIGEN_DEVICE_FUNC constexpr bool all_values_known_statically() const {
319    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::values_up_to_known_statically(*this);
320  }
321
322  EIGEN_DEVICE_FUNC constexpr bool values_statically_known_to_increase() const {
323    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::values_up_to_statically_known_to_increase(*this);
324  }
325};
326
327
328template<typename FirstType, typename... OtherTypes>
329constexpr IndexList<FirstType, OtherTypes...> make_index_list(FirstType val1, OtherTypes... other_vals) {
330  return IndexList<FirstType, OtherTypes...>(val1, other_vals...);
331}
332
333
334template<typename FirstType, typename... OtherTypes>
335struct IndexPairList : internal::IndexTuple<FirstType, OtherTypes...> {
336  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr IndexPair<DenseIndex> operator[] (const DenseIndex i) const {
337    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, IndexPair<DenseIndex>>::get(i, *this);
338  }
339  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC void set(const DenseIndex i, const IndexPair<DenseIndex> value) {
340    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...>>::value-1, IndexPair<DenseIndex> >::set(i, *this, value);
341  }
342
343  EIGEN_DEVICE_FUNC  constexpr IndexPairList(const internal::IndexTuple<FirstType, OtherTypes...>& other) : internal::IndexTuple<FirstType, OtherTypes...>(other) { }
344  EIGEN_DEVICE_FUNC  constexpr IndexPairList() : internal::IndexTuple<FirstType, OtherTypes...>() { }
345
346  EIGEN_DEVICE_FUNC constexpr bool value_known_statically(const DenseIndex i) const {
347    return internal::tuple_coeff<internal::array_size<internal::IndexTuple<FirstType, OtherTypes...> >::value-1, DenseIndex>::value_known_statically(i, *this);
348  }
349};
350
351namespace internal {
352
353template<typename FirstType, typename... OtherTypes> size_t array_prod(const IndexList<FirstType, OtherTypes...>& sizes) {
354  size_t result = 1;
355  for (int i = 0; i < array_size<IndexList<FirstType, OtherTypes...> >::value; ++i) {
356    result *= sizes[i];
357  }
358  return result;
359}
360
361template<typename FirstType, typename... OtherTypes> struct array_size<IndexList<FirstType, OtherTypes...> > {
362  static const size_t value = array_size<IndexTuple<FirstType, OtherTypes...> >::value;
363};
364template<typename FirstType, typename... OtherTypes> struct array_size<const IndexList<FirstType, OtherTypes...> > {
365  static const size_t value = array_size<IndexTuple<FirstType, OtherTypes...> >::value;
366};
367
368template<typename FirstType, typename... OtherTypes> struct array_size<IndexPairList<FirstType, OtherTypes...> > {
369  static const size_t value = std::tuple_size<std::tuple<FirstType, OtherTypes...> >::value;
370};
371template<typename FirstType, typename... OtherTypes> struct array_size<const IndexPairList<FirstType, OtherTypes...> > {
372  static const size_t value = std::tuple_size<std::tuple<FirstType, OtherTypes...> >::value;
373};
374
375template<DenseIndex N, typename FirstType, typename... OtherTypes> EIGEN_DEVICE_FUNC constexpr DenseIndex array_get(IndexList<FirstType, OtherTypes...>& a) {
376  return IndexTupleExtractor<N, FirstType, OtherTypes...>::get_val(a);
377}
378template<DenseIndex N, typename FirstType, typename... OtherTypes> EIGEN_DEVICE_FUNC constexpr DenseIndex array_get(const IndexList<FirstType, OtherTypes...>& a) {
379  return IndexTupleExtractor<N, FirstType, OtherTypes...>::get_val(a);
380}
381
382template <typename T>
383struct index_known_statically_impl {
384  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex) {
385    return false;
386  }
387};
388
389template <typename FirstType, typename... OtherTypes>
390struct index_known_statically_impl<IndexList<FirstType, OtherTypes...> > {
391  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i) {
392    return IndexList<FirstType, OtherTypes...>().value_known_statically(i);
393  }
394};
395
396template <typename FirstType, typename... OtherTypes>
397struct index_known_statically_impl<const IndexList<FirstType, OtherTypes...> > {
398  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i) {
399    return IndexList<FirstType, OtherTypes...>().value_known_statically(i);
400  }
401};
402
403
404template <typename T>
405struct all_indices_known_statically_impl {
406  static constexpr bool run() {
407    return false;
408  }
409};
410
411template <typename FirstType, typename... OtherTypes>
412struct all_indices_known_statically_impl<IndexList<FirstType, OtherTypes...> > {
413  EIGEN_DEVICE_FUNC static constexpr bool run() {
414    return IndexList<FirstType, OtherTypes...>().all_values_known_statically();
415  }
416};
417
418template <typename FirstType, typename... OtherTypes>
419struct all_indices_known_statically_impl<const IndexList<FirstType, OtherTypes...> > {
420  EIGEN_DEVICE_FUNC static constexpr bool run() {
421    return IndexList<FirstType, OtherTypes...>().all_values_known_statically();
422  }
423};
424
425
426template <typename T>
427struct indices_statically_known_to_increase_impl {
428  EIGEN_DEVICE_FUNC static constexpr bool run() {
429    return false;
430  }
431};
432
433template <typename FirstType, typename... OtherTypes>
434  struct indices_statically_known_to_increase_impl<IndexList<FirstType, OtherTypes...> > {
435  EIGEN_DEVICE_FUNC static constexpr bool run() {
436    return Eigen::IndexList<FirstType, OtherTypes...>().values_statically_known_to_increase();
437  }
438};
439
440template <typename FirstType, typename... OtherTypes>
441  struct indices_statically_known_to_increase_impl<const IndexList<FirstType, OtherTypes...> > {
442  EIGEN_DEVICE_FUNC static constexpr bool run() {
443    return Eigen::IndexList<FirstType, OtherTypes...>().values_statically_known_to_increase();
444  }
445};
446
447
448template <typename Tx>
449struct index_statically_eq_impl {
450  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
451    return false;
452  }
453};
454
455template <typename FirstType, typename... OtherTypes>
456struct index_statically_eq_impl<IndexList<FirstType, OtherTypes...> > {
457  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
458    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
459        (IndexList<FirstType, OtherTypes...>().get(i) == value);
460  }
461};
462
463template <typename FirstType, typename... OtherTypes>
464struct index_statically_eq_impl<const IndexList<FirstType, OtherTypes...> > {
465  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
466    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
467        (IndexList<FirstType, OtherTypes...>().get(i) == value);
468  }
469};
470
471
472template <typename T>
473struct index_statically_ne_impl {
474  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
475    return false;
476  }
477};
478
479template <typename FirstType, typename... OtherTypes>
480struct index_statically_ne_impl<IndexList<FirstType, OtherTypes...> > {
481  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
482    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
483        (IndexList<FirstType, OtherTypes...>().get(i) != value);
484  }
485};
486
487template <typename FirstType, typename... OtherTypes>
488struct index_statically_ne_impl<const IndexList<FirstType, OtherTypes...> > {
489  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
490    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
491        (IndexList<FirstType, OtherTypes...>().get(i) != value);
492  }
493};
494
495
496template <typename T>
497struct index_statically_gt_impl {
498  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
499    return false;
500  }
501};
502
503template <typename FirstType, typename... OtherTypes>
504struct index_statically_gt_impl<IndexList<FirstType, OtherTypes...> > {
505  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
506    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
507        (IndexList<FirstType, OtherTypes...>().get(i) > value);
508  }
509};
510
511template <typename FirstType, typename... OtherTypes>
512struct index_statically_gt_impl<const IndexList<FirstType, OtherTypes...> > {
513  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
514    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
515        (IndexList<FirstType, OtherTypes...>().get(i) > value);
516  }
517};
518
519
520
521template <typename T>
522struct index_statically_lt_impl {
523  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
524    return false;
525  }
526};
527
528template <typename FirstType, typename... OtherTypes>
529struct index_statically_lt_impl<IndexList<FirstType, OtherTypes...> > {
530  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
531    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
532        (IndexList<FirstType, OtherTypes...>().get(i) < value);
533  }
534};
535
536template <typename FirstType, typename... OtherTypes>
537struct index_statically_lt_impl<const IndexList<FirstType, OtherTypes...> > {
538  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
539    return IndexList<FirstType, OtherTypes...>().value_known_statically(i) &
540        (IndexList<FirstType, OtherTypes...>().get(i) < value);
541  }
542};
543
544
545
546template <typename Tx>
547struct index_pair_first_statically_eq_impl {
548  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
549    return false;
550  }
551};
552
553template <typename FirstType, typename... OtherTypes>
554struct index_pair_first_statically_eq_impl<IndexPairList<FirstType, OtherTypes...> > {
555  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
556    return IndexPairList<FirstType, OtherTypes...>().value_known_statically(i) &
557        (IndexPairList<FirstType, OtherTypes...>().operator[](i).first == value);
558  }
559};
560
561template <typename FirstType, typename... OtherTypes>
562struct index_pair_first_statically_eq_impl<const IndexPairList<FirstType, OtherTypes...> > {
563  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
564    return IndexPairList<FirstType, OtherTypes...>().value_known_statically(i) &
565        (IndexPairList<FirstType, OtherTypes...>().operator[](i).first == value);
566  }
567};
568
569
570
571template <typename Tx>
572struct index_pair_second_statically_eq_impl {
573  EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
574    return false;
575  }
576};
577
578template <typename FirstType, typename... OtherTypes>
579struct index_pair_second_statically_eq_impl<IndexPairList<FirstType, OtherTypes...> > {
580  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
581    return IndexPairList<FirstType, OtherTypes...>().value_known_statically(i) &
582        (IndexPairList<FirstType, OtherTypes...>().operator[](i).second == value);
583  }
584};
585
586template <typename FirstType, typename... OtherTypes>
587struct index_pair_second_statically_eq_impl<const IndexPairList<FirstType, OtherTypes...> > {
588  EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex i, const DenseIndex value) {
589    return IndexPairList<FirstType, OtherTypes...>().value_known_statically(i) &
590        (IndexPairList<FirstType, OtherTypes...>().operator[](i).second == value);
591  }
592};
593
594
595}  // end namespace internal
596}  // end namespace Eigen
597
598#else
599
600namespace Eigen {
601namespace internal {
602
603template <typename T>
604struct index_known_statically_impl {
605  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(const DenseIndex) {
606    return false;
607  }
608};
609
610template <typename T>
611struct all_indices_known_statically_impl {
612  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run() {
613    return false;
614  }
615};
616
617template <typename T>
618struct indices_statically_known_to_increase_impl {
619  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run() {
620    return false;
621  }
622};
623
624template <typename T>
625struct index_statically_eq_impl {
626  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
627    return false;
628  }
629};
630
631template <typename T>
632struct index_statically_ne_impl {
633  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
634    return false;
635  }
636};
637
638template <typename T>
639struct index_statically_gt_impl {
640  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
641    return false;
642  }
643};
644
645template <typename T>
646struct index_statically_lt_impl {
647  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
648    return false;
649  }
650};
651
652template <typename Tx>
653struct index_pair_first_statically_eq_impl {
654  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
655    return false;
656  }
657};
658
659template <typename Tx>
660struct index_pair_second_statically_eq_impl {
661  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
662    return false;
663  }
664};
665
666
667
668}  // end namespace internal
669}  // end namespace Eigen
670
671#endif
672
673
674namespace Eigen {
675namespace internal {
676template <typename T>
677static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_known_statically(DenseIndex i) {
678  return index_known_statically_impl<T>::run(i);
679}
680
681template <typename T>
682static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool all_indices_known_statically() {
683  return all_indices_known_statically_impl<T>::run();
684}
685
686template <typename T>
687static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool indices_statically_known_to_increase() {
688  return indices_statically_known_to_increase_impl<T>::run();
689}
690
691template <typename T>
692static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_eq(DenseIndex i, DenseIndex value) {
693  return index_statically_eq_impl<T>::run(i, value);
694}
695
696template <typename T>
697static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_ne(DenseIndex i, DenseIndex value) {
698  return index_statically_ne_impl<T>::run(i, value);
699}
700
701template <typename T>
702static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_gt(DenseIndex i, DenseIndex value) {
703  return index_statically_gt_impl<T>::run(i, value);
704}
705
706template <typename T>
707static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_statically_lt(DenseIndex i, DenseIndex value) {
708  return index_statically_lt_impl<T>::run(i, value);
709}
710
711template <typename T>
712static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_pair_first_statically_eq(DenseIndex i, DenseIndex value) {
713  return index_pair_first_statically_eq_impl<T>::run(i, value);
714}
715
716template <typename T>
717static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_pair_second_statically_eq(DenseIndex i, DenseIndex value) {
718  return index_pair_second_statically_eq_impl<T>::run(i, value);
719}
720
721}  // end namespace internal
722}  // end namespace Eigen
723
724
725#endif // EIGEN_CXX11_TENSOR_TENSOR_INDEX_LIST_H
726