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