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 15namespace Eigen { 16 17namespace 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 25struct empty_list { static const std::size_t count = 0; }; 26 27template<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 35struct null_type { }; 36 37template<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> 40struct 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 46template<> struct make_type_list<> { 47 typedef empty_list type; 48}; 49 50 51template <std::size_t index, class TList> struct get_type; 52 53template <class Head, class Tail> 54struct get_type<0, type_list<Head, Tail> > 55{ 56 typedef Head type; 57}; 58 59template <std::size_t i, class Head, class Tail> 60struct get_type<i, type_list<Head, Tail> > 61{ 62 typedef typename get_type<i-1, Tail>::type type; 63}; 64 65 66/* numeric list */ 67template <typename T, T n> 68struct type2val { 69 typedef T type; 70 static const T value = n; 71}; 72 73 74template<typename T, size_t n, T V> struct gen_numeric_list_repeated; 75 76template<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 80template<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 84template<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 88template<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 92template<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 96template<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 101template<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 107template<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 114template <std::size_t index, class NList> struct get; 115 116template <std::size_t i> 117struct get<i, empty_list> 118{ 119 get() { eigen_assert(false && "index overflow"); } 120 typedef void type; 121 static const char value = '\0'; 122}; 123 124template <std::size_t i, class Head> 125struct 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 132template <class Head> 133struct get<0, type_list<Head, empty_list> > 134{ 135 typedef typename Head::type type; 136 static const type value = Head::value; 137}; 138 139template <class Head, class Tail> 140struct get<0, type_list<Head, Tail> > 141{ 142 typedef typename Head::type type; 143 static const type value = Head::value; 144}; 145 146template <std::size_t i, class Head, class Tail> 147struct 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 154template <class NList> struct arg_prod { 155 static const typename NList::HeadType::type value = get<0, NList>::value * arg_prod<typename NList::TailType>::value; 156}; 157template <> struct arg_prod<empty_list> { 158 static const int value = 1; 159}; 160 161 162template<int n, typename t> 163array<t, n> repeat(t v) { 164 array<t, n> array; 165 array.fill(v); 166 return array; 167} 168 169template<std::size_t I, class Head, class Tail> 170EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list<Head, Tail>&) { 171 return get<I, type_list<Head, Tail> >::value; 172} 173template<std::size_t I, class Head, class Tail> 174EIGEN_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 178template <class NList> 179EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NList::HeadType::type array_prod(const NList&) { 180 return arg_prod<NList>::value; 181} 182 183template<typename t, std::size_t n> 184EIGEN_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} 189template<typename t> 190EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, 0>& /*a*/) { 191 return 0; 192} 193 194template<typename t> 195EIGEN_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 203template<std::size_t I, class T> 204EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(std::vector<T>& a) { 205 return a[I]; 206} 207template<std::size_t I, class T> 208EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const std::vector<T>& a) { 209 return a[I]; 210} 211 212struct sum_op { 213 template<typename A, typename B> static inline bool run(A a, B b) { return a + b; } 214}; 215struct product_op { 216 template<typename A, typename B> static inline bool run(A a, B b) { return a * b; } 217}; 218 219struct logical_and_op { 220 template<typename A, typename B> static inline bool run(A a, B b) { return a && b; } 221}; 222struct logical_or_op { 223 template<typename A, typename B> static inline bool run(A a, B b) { return a || b; } 224}; 225 226struct equal_op { 227 template<typename A, typename B> static inline bool run(A a, B b) { return a == b; } 228}; 229struct not_equal_op { 230 template<typename A, typename B> static inline bool run(A a, B b) { return a != b; } 231}; 232struct lesser_op { 233 template<typename A, typename B> static inline bool run(A a, B b) { return a < b; } 234}; 235struct lesser_equal_op { 236 template<typename A, typename B> static inline bool run(A a, B b) { return a <= b; } 237}; 238 239struct greater_op { 240 template<typename A, typename B> static inline bool run(A a, B b) { return a > b; } 241}; 242struct greater_equal_op { 243 template<typename A, typename B> static inline bool run(A a, B b) { return a >= b; } 244}; 245 246struct not_op { 247 template<typename A> static inline bool run(A a) { return !a; } 248}; 249struct negation_op { 250 template<typename A> static inline bool run(A a) { return -a; } 251}; 252struct greater_equal_zero_op { 253 template<typename A> static inline bool run(A a) { return a >= 0; } 254}; 255 256 257template<typename Reducer, typename Op, typename A, std::size_t N> 258struct 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 269template<typename Reducer, typename Op, typename A> 270struct ArrayApplyAndReduce<Reducer, Op, A, 1> { 271 static inline bool run(const array<A, 1>& a) { 272 return Op::run(a[0]); 273 } 274}; 275 276template<typename Reducer, typename Op, typename A, std::size_t N> 277inline bool array_apply_and_reduce(const array<A, N>& a) { 278 return ArrayApplyAndReduce<Reducer, Op, A, N>::run(a); 279} 280 281template<typename Reducer, typename Op, typename A, typename B, std::size_t N> 282struct 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 293template<typename Reducer, typename Op, typename A, typename B> 294struct 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 300template<typename Reducer, typename Op, typename A, typename B, std::size_t N> 301inline 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