// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2014 Benoit Steiner // // 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 { // The array class is only available starting with cxx11. Emulate our own here // if needed template class array { public: EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& operator[] (size_t index) { return values[index]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { return values[index]; } static EIGEN_ALWAYS_INLINE std::size_t size() { return n; } T values[n]; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array() { } explicit EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v) { EIGEN_STATIC_ASSERT(n==1, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2) { EIGEN_STATIC_ASSERT(n==2, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3) { EIGEN_STATIC_ASSERT(n==3, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4) { EIGEN_STATIC_ASSERT(n==4, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; values[3] = v4; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) { EIGEN_STATIC_ASSERT(n==5, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; values[3] = v4; values[4] = v5; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6) { EIGEN_STATIC_ASSERT(n==6, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; values[3] = v4; values[4] = v5; values[5] = v6; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7) { EIGEN_STATIC_ASSERT(n==7, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; values[3] = v4; values[4] = v5; values[5] = v6; values[6] = v7; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array( const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8) { EIGEN_STATIC_ASSERT(n==8, YOU_MADE_A_PROGRAMMING_MISTAKE) values[0] = v1; values[1] = v2; values[2] = v3; values[3] = v4; values[4] = v5; values[5] = v6; values[6] = v7; values[7] = v8; } #ifdef EIGEN_HAS_VARIADIC_TEMPLATES array(std::initializer_list l) { eigen_assert(l.size() == n); internal::smart_copy(l.begin(), l.end(), values); } #endif }; // Specialize array for zero size template class array { public: EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& operator[] (size_t index) { eigen_assert(false && "Can't index a zero size array"); return *static_cast(NULL); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { eigen_assert(false && "Can't index a zero size array"); return *static_cast(NULL); } static EIGEN_ALWAYS_INLINE std::size_t size() { return 0; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE array() { } #ifdef EIGEN_HAS_VARIADIC_TEMPLATES array(std::initializer_list l) { eigen_assert(l.size() == 0); } #endif }; namespace internal { /** \internal * \file CXX11/Core/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 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 struct make_type_list { typedef typename make_type_list::type tailresult; typedef type_list type; }; template<> struct make_type_list<> { typedef empty_list type; }; template struct get_type; template struct get_type<0, type_list > { typedef Head type; }; template struct get_type > { typedef typename get_type::type type; }; /* numeric list */ template struct type2val { typedef T type; static const T value = n; }; template struct gen_numeric_list_repeated; template struct gen_numeric_list_repeated { typedef typename make_type_list >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val, type2val, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val, type2val, type2val, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val, type2val, type2val, type2val, type2val >::type type; }; template struct gen_numeric_list_repeated { typedef typename make_type_list, type2val, type2val, type2val, type2val, type2val, type2val, type2val >::type type; }; template struct get; template struct get { get() { eigen_assert(false && "index overflow"); } typedef void type; static const char value = '\0'; }; template struct get > { get() { eigen_assert(false && "index overflow"); } typedef void type; static const char value = '\0'; }; template struct get<0, type_list > { typedef typename Head::type type; static const type value = Head::value; }; template struct get<0, type_list > { typedef typename Head::type type; static const type value = Head::value; }; template struct get > { typedef typename Tail::HeadType::type type; static const type value = get::value; }; template struct arg_prod { static const typename NList::HeadType::type value = get<0, NList>::value * arg_prod::value; }; template <> struct arg_prod { static const int value = 1; }; template array repeat(t v) { array array; array.fill(v); return array; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list& a) { return get >::value; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(const type_list& a) { return get >::value; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NList::HeadType::type array_prod(const NList& l) { return arg_prod::value; }; template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array& a) { t prod = 1; for (size_t i = 0; i < n; ++i) { prod *= a[i]; } return prod; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const std::vector& a) { t prod = 1; for (size_t i = 0; i < a.size(); ++i) { prod *= a[i]; } return prod; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array& a) { return a[I]; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array& a) { return a[I]; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(std::vector& a) { return a[I]; } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const std::vector& a) { return a[I]; } template struct array_size; template struct array_size > { static const size_t value = N; }; template struct array_size; template struct array_size& > { static const size_t value = N; }; template struct array_size; template struct array_size > { static const size_t value = N; }; template struct array_size; template struct array_size& > { static const size_t value = N; }; struct sum_op { template static inline bool run(A a, B b) { return a + b; } }; struct product_op { template static inline bool run(A a, B b) { return a * b; } }; struct logical_and_op { template static inline bool run(A a, B b) { return a && b; } }; struct logical_or_op { template static inline bool run(A a, B b) { return a || b; } }; struct equal_op { template static inline bool run(A a, B b) { return a == b; } }; struct not_equal_op { template static inline bool run(A a, B b) { return a != b; } }; struct lesser_op { template static inline bool run(A a, B b) { return a < b; } }; struct lesser_equal_op { template static inline bool run(A a, B b) { return a <= b; } }; struct greater_op { template static inline bool run(A a, B b) { return a > b; } }; struct greater_equal_op { template static inline bool run(A a, B b) { return a >= b; } }; struct not_op { template static inline bool run(A a) { return !a; } }; struct negation_op { template static inline bool run(A a) { return -a; } }; struct greater_equal_zero_op { template static inline bool run(A a) { return a >= 0; } }; template struct ArrayApplyAndReduce { static inline bool run(const array& 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 struct ArrayApplyAndReduce { static inline bool run(const array& a) { return Op::run(a[0]); } }; template inline bool array_apply_and_reduce(const array& a) { return ArrayApplyAndReduce::run(a); } template struct ArrayZipAndReduce { static inline bool run(const array& a, const array& 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 struct ArrayZipAndReduce { static inline bool run(const array& a, const array& b) { return Op::run(a[0], b[0]); } }; template inline bool array_zip_and_reduce(const array& a, const array& b) { return ArrayZipAndReduce::run(a, b); } } // end namespace internal } // end namespace Eigen #endif // EIGEN_EMULATE_CXX11_META_H