312 lines
9.2 KiB
C++
312 lines
9.2 KiB
C++
// 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 the mozilla.org home page
|
|
|
|
#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 1;
|
|
}
|
|
|
|
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
|