Home | History | Annotate | Download | only in Tensor
      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 (at) 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 
     18 namespace 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 
     40 template <DenseIndex n>
     41 struct 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>>().
     51 template <DenseIndex f, DenseIndex s>
     52 struct 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 
     67 template<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 
     84 namespace internal {
     85 template <typename T>
     86 EIGEN_DEVICE_FUNC void update_value(T& val, DenseIndex new_val) {
     87   val = new_val;
     88 }
     89 template <DenseIndex n>
     90 EIGEN_DEVICE_FUNC void update_value(type2index<n>& val, DenseIndex new_val) {
     91   val.set(new_val);
     92 }
     93 
     94 template <typename T>
     95 EIGEN_DEVICE_FUNC void update_value(T& val, IndexPair<DenseIndex> new_val) {
     96   val = new_val;
     97 }
     98 template <DenseIndex f, DenseIndex s>
     99 EIGEN_DEVICE_FUNC void update_value(type2indexpair<f, s>& val, IndexPair<DenseIndex> new_val) {
    100   val.set(new_val);
    101 }
    102 
    103 
    104 template <typename T>
    105 struct is_compile_time_constant {
    106   static constexpr bool value = false;
    107 };
    108 
    109 template <DenseIndex idx>
    110 struct is_compile_time_constant<type2index<idx> > {
    111   static constexpr bool value = true;
    112 };
    113 template <DenseIndex idx>
    114 struct is_compile_time_constant<const type2index<idx> > {
    115   static constexpr bool value = true;
    116 };
    117 template <DenseIndex idx>
    118 struct is_compile_time_constant<type2index<idx>& > {
    119   static constexpr bool value = true;
    120 };
    121 template <DenseIndex idx>
    122 struct is_compile_time_constant<const type2index<idx>& > {
    123   static constexpr bool value = true;
    124 };
    125 
    126 template <DenseIndex f, DenseIndex s>
    127 struct is_compile_time_constant<type2indexpair<f, s> > {
    128   static constexpr bool value = true;
    129 };
    130 template <DenseIndex f, DenseIndex s>
    131 struct is_compile_time_constant<const type2indexpair<f, s> > {
    132   static constexpr bool value = true;
    133 };
    134 template <DenseIndex f, DenseIndex s>
    135 struct is_compile_time_constant<type2indexpair<f, s>& > {
    136   static constexpr bool value = true;
    137 };
    138 template <DenseIndex f, DenseIndex s>
    139 struct is_compile_time_constant<const type2indexpair<f, s>& > {
    140   static constexpr bool value = true;
    141 };
    142 
    143 
    144 template<typename... T>
    145 struct IndexTuple;
    146 
    147 template<typename T, typename... O>
    148 struct 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 
    159 template<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 
    170 template<int N, typename... T>
    171 struct IndexTupleExtractor;
    172 
    173 template<int N, typename T, typename... O>
    174 struct 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 
    192 template<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 
    211 template <int N, typename T, typename... O>
    212 EIGEN_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 }
    215 template <int N, typename T, typename... O>
    216 EIGEN_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 }
    219 template <typename T, typename... O>
    220   struct array_size<IndexTuple<T, O...> > {
    221   static const size_t value = IndexTuple<T, O...>::count;
    222 };
    223 template <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 
    231 template <DenseIndex Idx, typename ValueT>
    232 struct 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 
    268 template <typename ValueT>
    269 struct 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 
    299 template<typename FirstType, typename... OtherTypes>
    300 struct 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 
    328 template<typename FirstType, typename... OtherTypes>
    329 constexpr IndexList<FirstType, OtherTypes...> make_index_list(FirstType val1, OtherTypes... other_vals) {
    330   return IndexList<FirstType, OtherTypes...>(val1, other_vals...);
    331 }
    332 
    333 
    334 template<typename FirstType, typename... OtherTypes>
    335 struct 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 
    351 namespace internal {
    352 
    353 template<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 
    361 template<typename FirstType, typename... OtherTypes> struct array_size<IndexList<FirstType, OtherTypes...> > {
    362   static const size_t value = array_size<IndexTuple<FirstType, OtherTypes...> >::value;
    363 };
    364 template<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 
    368 template<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 };
    371 template<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 
    375 template<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 }
    378 template<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 
    382 template <typename T>
    383 struct index_known_statically_impl {
    384   EIGEN_DEVICE_FUNC static constexpr bool run(const DenseIndex) {
    385     return false;
    386   }
    387 };
    388 
    389 template <typename FirstType, typename... OtherTypes>
    390 struct 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 
    396 template <typename FirstType, typename... OtherTypes>
    397 struct 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 
    404 template <typename T>
    405 struct all_indices_known_statically_impl {
    406   static constexpr bool run() {
    407     return false;
    408   }
    409 };
    410 
    411 template <typename FirstType, typename... OtherTypes>
    412 struct 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 
    418 template <typename FirstType, typename... OtherTypes>
    419 struct 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 
    426 template <typename T>
    427 struct indices_statically_known_to_increase_impl {
    428   EIGEN_DEVICE_FUNC static constexpr bool run() {
    429     return false;
    430   }
    431 };
    432 
    433 template <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 
    440 template <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 
    448 template <typename Tx>
    449 struct index_statically_eq_impl {
    450   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    451     return false;
    452   }
    453 };
    454 
    455 template <typename FirstType, typename... OtherTypes>
    456 struct 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 
    463 template <typename FirstType, typename... OtherTypes>
    464 struct 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 
    472 template <typename T>
    473 struct index_statically_ne_impl {
    474   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    475     return false;
    476   }
    477 };
    478 
    479 template <typename FirstType, typename... OtherTypes>
    480 struct 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 
    487 template <typename FirstType, typename... OtherTypes>
    488 struct 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 
    496 template <typename T>
    497 struct index_statically_gt_impl {
    498   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    499     return false;
    500   }
    501 };
    502 
    503 template <typename FirstType, typename... OtherTypes>
    504 struct 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 
    511 template <typename FirstType, typename... OtherTypes>
    512 struct 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 
    521 template <typename T>
    522 struct index_statically_lt_impl {
    523   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    524     return false;
    525   }
    526 };
    527 
    528 template <typename FirstType, typename... OtherTypes>
    529 struct 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 
    536 template <typename FirstType, typename... OtherTypes>
    537 struct 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 
    546 template <typename Tx>
    547 struct index_pair_first_statically_eq_impl {
    548   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    549     return false;
    550   }
    551 };
    552 
    553 template <typename FirstType, typename... OtherTypes>
    554 struct 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 
    561 template <typename FirstType, typename... OtherTypes>
    562 struct 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 
    571 template <typename Tx>
    572 struct index_pair_second_statically_eq_impl {
    573   EIGEN_DEVICE_FUNC static constexpr bool run(DenseIndex, DenseIndex) {
    574     return false;
    575   }
    576 };
    577 
    578 template <typename FirstType, typename... OtherTypes>
    579 struct 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 
    586 template <typename FirstType, typename... OtherTypes>
    587 struct 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 
    600 namespace Eigen {
    601 namespace internal {
    602 
    603 template <typename T>
    604 struct index_known_statically_impl {
    605   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(const DenseIndex) {
    606     return false;
    607   }
    608 };
    609 
    610 template <typename T>
    611 struct all_indices_known_statically_impl {
    612   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run() {
    613     return false;
    614   }
    615 };
    616 
    617 template <typename T>
    618 struct indices_statically_known_to_increase_impl {
    619   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run() {
    620     return false;
    621   }
    622 };
    623 
    624 template <typename T>
    625 struct index_statically_eq_impl {
    626   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
    627     return false;
    628   }
    629 };
    630 
    631 template <typename T>
    632 struct index_statically_ne_impl {
    633   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
    634     return false;
    635   }
    636 };
    637 
    638 template <typename T>
    639 struct index_statically_gt_impl {
    640   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
    641     return false;
    642   }
    643 };
    644 
    645 template <typename T>
    646 struct index_statically_lt_impl {
    647   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
    648     return false;
    649   }
    650 };
    651 
    652 template <typename Tx>
    653 struct index_pair_first_statically_eq_impl {
    654   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool run(DenseIndex, DenseIndex) {
    655     return false;
    656   }
    657 };
    658 
    659 template <typename Tx>
    660 struct 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 
    674 namespace Eigen {
    675 namespace internal {
    676 template <typename T>
    677 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool index_known_statically(DenseIndex i) {
    678   return index_known_statically_impl<T>::run(i);
    679 }
    680 
    681 template <typename T>
    682 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool all_indices_known_statically() {
    683   return all_indices_known_statically_impl<T>::run();
    684 }
    685 
    686 template <typename T>
    687 static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR bool indices_statically_known_to_increase() {
    688   return indices_statically_known_to_increase_impl<T>::run();
    689 }
    690 
    691 template <typename T>
    692 static 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 
    696 template <typename T>
    697 static 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 
    701 template <typename T>
    702 static 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 
    706 template <typename T>
    707 static 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 
    711 template <typename T>
    712 static 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 
    716 template <typename T>
    717 static 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