|  | // This file is part of Eigen, a lightweight C++ template library | 
|  | // for linear algebra. | 
|  | // | 
|  | // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> | 
|  | // | 
|  | // This Source Code Form is subject to the terms of the Mozilla | 
|  | // Public License v. 2.0. If a copy of the MPL was not distributed | 
|  | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
|  |  | 
|  | #ifndef EIGEN_EMULATE_CXX11_META_H | 
|  | #define EIGEN_EMULATE_CXX11_META_H | 
|  |  | 
|  |  | 
|  |  | 
|  | namespace Eigen { | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | /** \internal | 
|  | * \file CXX11/util/EmulateCXX11Meta.h | 
|  | * This file emulates a subset of the functionality provided by CXXMeta.h for | 
|  | * compilers that don't yet support cxx11 such as nvcc. | 
|  | */ | 
|  |  | 
|  | struct empty_list { static const std::size_t count = 0; }; | 
|  |  | 
|  | template<typename T, typename Tail=empty_list> struct type_list { | 
|  | typedef T HeadType; | 
|  | typedef Tail TailType; | 
|  | static const T head; | 
|  | static const Tail tail; | 
|  | static const std::size_t count = 1 + Tail::count; | 
|  | }; | 
|  |  | 
|  | struct null_type { }; | 
|  |  | 
|  | template<typename T1 = null_type, typename T2 = null_type, typename T3 = null_type, | 
|  | typename T4 = null_type, typename T5 = null_type, typename T6 = null_type, | 
|  | typename T7 = null_type, typename T8 = null_type> | 
|  | struct make_type_list { | 
|  | typedef typename make_type_list<T2, T3, T4, T5, T6, T7, T8>::type tailresult; | 
|  |  | 
|  | typedef type_list<T1, tailresult> type; | 
|  | }; | 
|  |  | 
|  | template<> struct make_type_list<> { | 
|  | typedef empty_list type; | 
|  | }; | 
|  |  | 
|  |  | 
|  | template <std::size_t index, class TList> struct get_type; | 
|  |  | 
|  | template <class Head, class Tail> | 
|  | struct get_type<0, type_list<Head, Tail> > | 
|  | { | 
|  | typedef Head type; | 
|  | }; | 
|  |  | 
|  | template <std::size_t i, class Head, class Tail> | 
|  | struct get_type<i, type_list<Head, Tail> > | 
|  | { | 
|  | typedef typename get_type<i-1, Tail>::type type; | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* numeric list */ | 
|  | template <typename T, T n> | 
|  | struct type2val { | 
|  | typedef T type; | 
|  | static const T value = n; | 
|  | }; | 
|  |  | 
|  |  | 
|  | template<typename T, size_t n, T V> struct gen_numeric_list_repeated; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 1, V> { | 
|  | typedef typename make_type_list<type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 2, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 3, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 4, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 5, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 6, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, | 
|  | type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 7, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, | 
|  | type2val<T, V>, type2val<T, V>, type2val<T, V>, | 
|  | type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  | template<typename T, T V> struct gen_numeric_list_repeated<T, 8, V> { | 
|  | typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, | 
|  | type2val<T, V>, type2val<T, V>, type2val<T, V>, | 
|  | type2val<T, V>, type2val<T, V> >::type type; | 
|  | }; | 
|  |  | 
|  |  | 
|  | template <std::size_t index, class NList> struct get; | 
|  |  | 
|  | template <std::size_t i> | 
|  | struct get<i, empty_list> | 
|  | { | 
|  | get() { eigen_assert(false && "index overflow"); } | 
|  | typedef void type; | 
|  | static const char value = '\0'; | 
|  | }; | 
|  |  | 
|  | template <std::size_t i, class Head> | 
|  | struct get<i, type_list<Head, empty_list> > | 
|  | { | 
|  | get() { eigen_assert(false && "index overflow"); } | 
|  | typedef void type; | 
|  | static const char value = '\0'; | 
|  | }; | 
|  |  | 
|  | template <class Head> | 
|  | struct get<0, type_list<Head, empty_list> > | 
|  | { | 
|  | typedef typename Head::type type; | 
|  | static const type value = Head::value; | 
|  | }; | 
|  |  | 
|  | template <class Head, class Tail> | 
|  | struct get<0, type_list<Head, Tail> > | 
|  | { | 
|  | typedef typename Head::type type; | 
|  | static const type value = Head::value; | 
|  | }; | 
|  |  | 
|  | template <std::size_t i, class Head, class Tail> | 
|  | struct get<i, type_list<Head, Tail> > | 
|  | { | 
|  | typedef typename Tail::HeadType::type type; | 
|  | static const type value = get<i-1, Tail>::value; | 
|  | }; | 
|  |  | 
|  |  | 
|  | template <class NList> struct arg_prod { | 
|  | static const typename NList::HeadType::type value = get<0, NList>::value * arg_prod<typename NList::TailType>::value; | 
|  | }; | 
|  | template <> struct arg_prod<empty_list> { | 
|  | static const int value = 1; | 
|  | }; | 
|  |  | 
|  |  | 
|  | template<int n, typename t> | 
|  | array<t, n> repeat(t v) { | 
|  | array<t, n> array; | 
|  | array.fill(v); | 
|  | return array; | 
|  | } | 
|  |  | 
|  | template<std::size_t I, class Head, class Tail> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list<Head, Tail>&) { | 
|  | return get<I, type_list<Head, Tail> >::value; | 
|  | } | 
|  | template<std::size_t I, class Head, class Tail> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(const type_list<Head, Tail>&) { | 
|  | return get<I, type_list<Head, Tail> >::value; | 
|  | } | 
|  |  | 
|  | template <class NList> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NList::HeadType::type array_prod(const NList&) { | 
|  | return arg_prod<NList>::value; | 
|  | } | 
|  |  | 
|  | template<typename t, std::size_t n> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, n>& a) { | 
|  | t prod = 1; | 
|  | for (size_t i = 0; i < n; ++i) { prod *= a[i]; } | 
|  | return prod; | 
|  | } | 
|  | template<typename t> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, 0>& /*a*/) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | template<typename t> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const std::vector<t>& a) { | 
|  | eigen_assert(a.size() > 0); | 
|  | t prod = 1; | 
|  | for (size_t i = 0; i < a.size(); ++i) { prod *= a[i]; } | 
|  | return prod; | 
|  | } | 
|  |  | 
|  |  | 
|  | template<std::size_t I, class T> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(std::vector<T>& a) { | 
|  | return a[I]; | 
|  | } | 
|  | template<std::size_t I, class T> | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const std::vector<T>& a) { | 
|  | return a[I]; | 
|  | } | 
|  |  | 
|  | struct sum_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a + b; } | 
|  | }; | 
|  | struct product_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a * b; } | 
|  | }; | 
|  |  | 
|  | struct logical_and_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a && b; } | 
|  | }; | 
|  | struct logical_or_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a || b; } | 
|  | }; | 
|  |  | 
|  | struct equal_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a == b; } | 
|  | }; | 
|  | struct not_equal_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a != b; } | 
|  | }; | 
|  | struct lesser_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a < b; } | 
|  | }; | 
|  | struct lesser_equal_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a <= b; } | 
|  | }; | 
|  |  | 
|  | struct greater_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a > b; } | 
|  | }; | 
|  | struct greater_equal_op { | 
|  | template<typename A, typename B> static inline bool run(A a, B b) { return a >= b; } | 
|  | }; | 
|  |  | 
|  | struct not_op { | 
|  | template<typename A> static inline bool run(A a) { return !a; } | 
|  | }; | 
|  | struct negation_op { | 
|  | template<typename A> static inline bool run(A a) { return -a; } | 
|  | }; | 
|  | struct greater_equal_zero_op { | 
|  | template<typename A> static inline bool run(A a) { return a >= 0; } | 
|  | }; | 
|  |  | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A, std::size_t N> | 
|  | struct ArrayApplyAndReduce { | 
|  | static inline bool run(const array<A, N>& a) { | 
|  | EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE); | 
|  | bool result = Reducer::run(Op::run(a[0]), Op::run(a[1])); | 
|  | for (size_t i = 2; i < N; ++i) { | 
|  | result = Reducer::run(result, Op::run(a[i])); | 
|  | } | 
|  | return result; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A> | 
|  | struct ArrayApplyAndReduce<Reducer, Op, A, 1>  { | 
|  | static inline bool run(const array<A, 1>& a) { | 
|  | return Op::run(a[0]); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A, std::size_t N> | 
|  | inline bool array_apply_and_reduce(const array<A, N>& a) { | 
|  | return ArrayApplyAndReduce<Reducer, Op, A, N>::run(a); | 
|  | } | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A, typename B, std::size_t N> | 
|  | struct ArrayZipAndReduce { | 
|  | static inline bool run(const array<A, N>& a, const array<B, N>& b) { | 
|  | EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE); | 
|  | bool result = Reducer::run(Op::run(a[0], b[0]), Op::run(a[1], b[1])); | 
|  | for (size_t i = 2; i < N; ++i) { | 
|  | result = Reducer::run(result, Op::run(a[i], b[i])); | 
|  | } | 
|  | return result; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A, typename B> | 
|  | struct ArrayZipAndReduce<Reducer, Op, A, B, 1> { | 
|  | static inline bool run(const array<A, 1>& a, const array<B, 1>& b) { | 
|  | return Op::run(a[0], b[0]); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename Reducer, typename Op, typename A, typename B, std::size_t N> | 
|  | inline bool array_zip_and_reduce(const array<A, N>& a, const array<B, N>& b) { | 
|  | return ArrayZipAndReduce<Reducer, Op, A, B, N>::run(a, b); | 
|  | } | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  | }  // end namespace Eigen | 
|  |  | 
|  |  | 
|  |  | 
|  | #endif  // EIGEN_EMULATE_CXX11_META_H |