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