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