Home | History | Annotate | Download | only in util
      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_EMULATE_CXX11_META_H
     11 #define EIGEN_EMULATE_CXX11_META_H
     12 
     13 
     14 
     15 namespace Eigen {
     16 
     17 namespace internal {
     18 
     19 /** \internal
     20   * \file CXX11/util/EmulateCXX11Meta.h
     21   * This file emulates a subset of the functionality provided by CXXMeta.h for
     22   * compilers that don't yet support cxx11 such as nvcc.
     23   */
     24 
     25 struct empty_list { static const std::size_t count = 0; };
     26 
     27 template<typename T, typename Tail=empty_list> struct type_list {
     28   typedef T HeadType;
     29   typedef Tail TailType;
     30   static const T head;
     31   static const Tail tail;
     32   static const std::size_t count = 1 + Tail::count;
     33 };
     34 
     35 struct null_type { };
     36 
     37 template<typename T1 = null_type, typename T2 = null_type, typename T3 = null_type,
     38          typename T4 = null_type, typename T5 = null_type, typename T6 = null_type,
     39          typename T7 = null_type, typename T8 = null_type>
     40 struct make_type_list {
     41   typedef typename make_type_list<T2, T3, T4, T5, T6, T7, T8>::type tailresult;
     42 
     43   typedef type_list<T1, tailresult> type;
     44 };
     45 
     46 template<> struct make_type_list<> {
     47   typedef empty_list type;
     48 };
     49 
     50 
     51 template <std::size_t index, class TList> struct get_type;
     52 
     53 template <class Head, class Tail>
     54 struct get_type<0, type_list<Head, Tail> >
     55 {
     56   typedef Head type;
     57 };
     58 
     59 template <std::size_t i, class Head, class Tail>
     60 struct get_type<i, type_list<Head, Tail> >
     61 {
     62   typedef typename get_type<i-1, Tail>::type type;
     63 };
     64 
     65 
     66 /* numeric list */
     67 template <typename T, T n>
     68 struct type2val {
     69   typedef T type;
     70   static const T value = n;
     71 };
     72 
     73 
     74 template<typename T, size_t n, T V> struct gen_numeric_list_repeated;
     75 
     76 template<typename T, T V> struct gen_numeric_list_repeated<T, 1, V> {
     77   typedef typename make_type_list<type2val<T, V> >::type type;
     78 };
     79 
     80 template<typename T, T V> struct gen_numeric_list_repeated<T, 2, V> {
     81   typedef typename make_type_list<type2val<T, V>, type2val<T, V> >::type type;
     82 };
     83 
     84 template<typename T, T V> struct gen_numeric_list_repeated<T, 3, V> {
     85   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
     86 };
     87 
     88 template<typename T, T V> struct gen_numeric_list_repeated<T, 4, V> {
     89   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
     90 };
     91 
     92 template<typename T, T V> struct gen_numeric_list_repeated<T, 5, V> {
     93   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
     94 };
     95 
     96 template<typename T, T V> struct gen_numeric_list_repeated<T, 6, V> {
     97   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
     98                                   type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
     99 };
    100 
    101 template<typename T, T V> struct gen_numeric_list_repeated<T, 7, V> {
    102   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
    103                                   type2val<T, V>, type2val<T, V>, type2val<T, V>,
    104                                   type2val<T, V> >::type type;
    105 };
    106 
    107 template<typename T, T V> struct gen_numeric_list_repeated<T, 8, V> {
    108   typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
    109                                   type2val<T, V>, type2val<T, V>, type2val<T, V>,
    110                                   type2val<T, V>, type2val<T, V> >::type type;
    111 };
    112 
    113 
    114 template <std::size_t index, class NList> struct get;
    115 
    116 template <std::size_t i>
    117 struct get<i, empty_list>
    118 {
    119   get() { eigen_assert(false && "index overflow"); }
    120   typedef void type;
    121   static const char value = '\0';
    122 };
    123 
    124 template <std::size_t i, class Head>
    125 struct get<i, type_list<Head, empty_list> >
    126 {
    127   get() { eigen_assert(false && "index overflow"); }
    128   typedef void type;
    129   static const char value = '\0';
    130 };
    131 
    132 template <class Head>
    133 struct get<0, type_list<Head, empty_list> >
    134 {
    135   typedef typename Head::type type;
    136   static const type value = Head::value;
    137 };
    138 
    139 template <class Head, class Tail>
    140 struct get<0, type_list<Head, Tail> >
    141 {
    142   typedef typename Head::type type;
    143   static const type value = Head::value;
    144 };
    145 
    146 template <std::size_t i, class Head, class Tail>
    147 struct get<i, type_list<Head, Tail> >
    148 {
    149   typedef typename Tail::HeadType::type type;
    150   static const type value = get<i-1, Tail>::value;
    151 };
    152 
    153 
    154 template <class NList> struct arg_prod {
    155   static const typename NList::HeadType::type value = get<0, NList>::value * arg_prod<typename NList::TailType>::value;
    156 };
    157 template <> struct arg_prod<empty_list> {
    158   static const int value = 1;
    159 };
    160 
    161 
    162 template<int n, typename t>
    163 array<t, n> repeat(t v) {
    164   array<t, n> array;
    165   array.fill(v);
    166   return array;
    167 }
    168 
    169 template<std::size_t I, class Head, class Tail>
    170 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list<Head, Tail>&) {
    171   return get<I, type_list<Head, Tail> >::value;
    172 }
    173 template<std::size_t I, class Head, class Tail>
    174 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(const type_list<Head, Tail>&) {
    175   return get<I, type_list<Head, Tail> >::value;
    176 }
    177 
    178 template <class NList>
    179 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NList::HeadType::type array_prod(const NList&) {
    180   return arg_prod<NList>::value;
    181 }
    182 
    183 template<typename t, std::size_t n>
    184 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, n>& a) {
    185   t prod = 1;
    186   for (size_t i = 0; i < n; ++i) { prod *= a[i]; }
    187   return prod;
    188 }
    189 template<typename t>
    190 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, 0>& /*a*/) {
    191   return 0;
    192 }
    193 
    194 template<typename t>
    195 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const std::vector<t>& a) {
    196   eigen_assert(a.size() > 0);
    197   t prod = 1;
    198   for (size_t i = 0; i < a.size(); ++i) { prod *= a[i]; }
    199   return prod;
    200 }
    201 
    202 
    203 template<std::size_t I, class T>
    204 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(std::vector<T>& a) {
    205   return a[I];
    206 }
    207 template<std::size_t I, class T>
    208 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const std::vector<T>& a) {
    209   return a[I];
    210 }
    211 
    212 struct sum_op {
    213   template<typename A, typename B> static inline bool run(A a, B b) { return a + b; }
    214 };
    215 struct product_op {
    216   template<typename A, typename B> static inline bool run(A a, B b) { return a * b; }
    217 };
    218 
    219 struct logical_and_op {
    220   template<typename A, typename B> static inline bool run(A a, B b) { return a && b; }
    221 };
    222 struct logical_or_op {
    223   template<typename A, typename B> static inline bool run(A a, B b) { return a || b; }
    224 };
    225 
    226 struct equal_op {
    227   template<typename A, typename B> static inline bool run(A a, B b) { return a == b; }
    228 };
    229 struct not_equal_op {
    230   template<typename A, typename B> static inline bool run(A a, B b) { return a != b; }
    231 };
    232 struct lesser_op {
    233   template<typename A, typename B> static inline bool run(A a, B b) { return a < b; }
    234 };
    235 struct lesser_equal_op {
    236   template<typename A, typename B> static inline bool run(A a, B b) { return a <= b; }
    237 };
    238 
    239 struct greater_op {
    240   template<typename A, typename B> static inline bool run(A a, B b) { return a > b; }
    241 };
    242 struct greater_equal_op {
    243   template<typename A, typename B> static inline bool run(A a, B b) { return a >= b; }
    244 };
    245 
    246 struct not_op {
    247   template<typename A> static inline bool run(A a) { return !a; }
    248 };
    249 struct negation_op {
    250   template<typename A> static inline bool run(A a) { return -a; }
    251 };
    252 struct greater_equal_zero_op {
    253   template<typename A> static inline bool run(A a) { return a >= 0; }
    254 };
    255 
    256 
    257 template<typename Reducer, typename Op, typename A, std::size_t N>
    258 struct ArrayApplyAndReduce {
    259   static inline bool run(const array<A, N>& a) {
    260     EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE);
    261     bool result = Reducer::run(Op::run(a[0]), Op::run(a[1]));
    262     for (size_t i = 2; i < N; ++i) {
    263       result = Reducer::run(result, Op::run(a[i]));
    264     }
    265     return result;
    266   }
    267 };
    268 
    269 template<typename Reducer, typename Op, typename A>
    270 struct ArrayApplyAndReduce<Reducer, Op, A, 1>  {
    271   static inline bool run(const array<A, 1>& a) {
    272     return Op::run(a[0]);
    273   }
    274 };
    275 
    276 template<typename Reducer, typename Op, typename A, std::size_t N>
    277 inline bool array_apply_and_reduce(const array<A, N>& a) {
    278   return ArrayApplyAndReduce<Reducer, Op, A, N>::run(a);
    279 }
    280 
    281 template<typename Reducer, typename Op, typename A, typename B, std::size_t N>
    282 struct ArrayZipAndReduce {
    283   static inline bool run(const array<A, N>& a, const array<B, N>& b) {
    284     EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE);
    285     bool result = Reducer::run(Op::run(a[0], b[0]), Op::run(a[1], b[1]));
    286     for (size_t i = 2; i < N; ++i) {
    287       result = Reducer::run(result, Op::run(a[i], b[i]));
    288     }
    289     return result;
    290   }
    291 };
    292 
    293 template<typename Reducer, typename Op, typename A, typename B>
    294 struct ArrayZipAndReduce<Reducer, Op, A, B, 1> {
    295   static inline bool run(const array<A, 1>& a, const array<B, 1>& b) {
    296     return Op::run(a[0], b[0]);
    297   }
    298 };
    299 
    300 template<typename Reducer, typename Op, typename A, typename B, std::size_t N>
    301 inline bool array_zip_and_reduce(const array<A, N>& a, const array<B, N>& b) {
    302   return ArrayZipAndReduce<Reducer, Op, A, B, N>::run(a, b);
    303 }
    304 
    305 }  // end namespace internal
    306 
    307 }  // end namespace Eigen
    308 
    309 
    310 
    311 #endif  // EIGEN_EMULATE_CXX11_META_H
    312