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_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