Commit 24c57ef1 authored by Florian Maurin's avatar Florian Maurin Committed by Rasmus Munk Larsen
Browse files

Core: Replace recursive utility expansions

parent 07612387
Loading
Loading
Loading
Loading
Loading
+8 −35
Original line number Diff line number Diff line
@@ -527,41 +527,14 @@ struct pow_impl<ScalarX, ScalarY, true> {
  }
};

enum { meta_floor_log2_terminate, meta_floor_log2_move_up, meta_floor_log2_move_down, meta_floor_log2_bogus };

template <unsigned int n, int lower, int upper>
struct meta_floor_log2_selector {
  enum {
    middle = (lower + upper) / 2,
    value = (upper <= lower + 1)  ? int(meta_floor_log2_terminate)
            : (n < (1 << middle)) ? int(meta_floor_log2_move_down)
            : (n == 0)            ? int(meta_floor_log2_bogus)
                                  : int(meta_floor_log2_move_up)
  };
};

template <unsigned int n, int lower = 0, int upper = sizeof(unsigned int) * CHAR_BIT - 1,
          int selector = meta_floor_log2_selector<n, lower, upper>::value>
struct meta_floor_log2 {};

template <unsigned int n, int lower, int upper>
struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_down>
    : std::integral_constant<int, meta_floor_log2<n, lower, meta_floor_log2_selector<n, lower, upper>::middle>::value> {
};

template <unsigned int n, int lower, int upper>
struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_up>
    : std::integral_constant<int, meta_floor_log2<n, meta_floor_log2_selector<n, lower, upper>::middle, upper>::value> {
};

template <unsigned int n, int lower, int upper>
struct meta_floor_log2<n, lower, upper, meta_floor_log2_terminate>
    : std::integral_constant<int, (n >= ((unsigned int)(1) << (lower + 1))) ? lower + 1 : lower> {};

template <unsigned int n, int lower, int upper>
struct meta_floor_log2<n, lower, upper, meta_floor_log2_bogus> {
  // no value, error at compile time
};
constexpr int floor_log2(unsigned int value) {
  int result = 0;
  while (value > 1) {
    value >>= 1;
    ++result;
  }
  return result;
}

template <typename BitsType, typename EnableIf = void>
struct count_bits_impl {
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ inline Scalar random() {
// TODO: replace or provide alternatives to this, e.g. std::random_device
struct eigen_random_device {
  using ReturnType = int;
  static constexpr int Entropy = meta_floor_log2<(unsigned int)(RAND_MAX) + 1>::value;
  static constexpr int Entropy = floor_log2((unsigned int)(RAND_MAX) + 1);
  static constexpr ReturnType Highest = RAND_MAX;
  static EIGEN_DEVICE_FUNC inline ReturnType run() { return std::rand(); }
};
+13 −14
Original line number Diff line number Diff line
@@ -241,31 +241,30 @@ constexpr auto arg_sum(Ts... ts) {

/* generic array reductions */

// can't reuse standard reduce() interface above because Intel's Compiler
// *really* doesn't like it, so we just reimplement the stuff
// (start from N - 1 and work down to 0 because specialization for
// n == N - 1 also doesn't work in Intel's compiler, so it goes into
// an infinite loop)
template <typename Reducer, typename T, std::size_t N, std::size_t n = N - 1>
struct h_array_reduce {
  EIGEN_DEVICE_FUNC constexpr static auto run(const array<T, N>& arr, T identity) {
    return Reducer::run(h_array_reduce<Reducer, T, N, n - 1>::run(arr, identity), array_get<n>(arr));
template <typename Reducer, typename T, std::size_t N>
struct array_reducer {
  EIGEN_DEVICE_FUNC constexpr static auto run(const array<T, N>& arr, T) {
    auto result = Reducer::run(arr[0], arr[1]);
    for (std::size_t i = 2; i < N; ++i) {
      result = Reducer::run(result, arr[i]);
    }
    return result;
  }
};

template <typename Reducer, typename T, std::size_t N>
struct h_array_reduce<Reducer, T, N, 0> {
  EIGEN_DEVICE_FUNC constexpr static T run(const array<T, N>& arr, T) { return array_get<0>(arr); }
template <typename Reducer, typename T>
struct array_reducer<Reducer, T, 1> {
  EIGEN_DEVICE_FUNC constexpr static T run(const array<T, 1>& arr, T) { return arr[0]; }
};

template <typename Reducer, typename T>
struct h_array_reduce<Reducer, T, 0> {
struct array_reducer<Reducer, T, 0> {
  EIGEN_DEVICE_FUNC constexpr static T run(const array<T, 0>&, T identity) { return identity; }
};

template <typename Reducer, typename T, std::size_t N>
EIGEN_DEVICE_FUNC constexpr auto array_reduce(const array<T, N>& arr, T identity) {
  return h_array_reduce<Reducer, T, N>::run(arr, identity);
  return array_reducer<Reducer, T, N>::run(arr, identity);
}

/* standard array reductions */
+24 −38
Original line number Diff line number Diff line
@@ -123,46 +123,23 @@ class Serializer<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>

namespace internal {

// Recursive serialization implementation helper.
template <size_t N, typename... Types>
struct serialize_impl;

template <size_t N, typename T1, typename... Ts>
struct serialize_impl<N, T1, Ts...> {
  using Serializer = Eigen::Serializer<std::decay_t<T1>>;

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size(const T1& value, const Ts&... args) {
    Serializer serializer;
    size_t size = serializer.size(value);
    return size + serialize_impl<N - 1, Ts...>::serialize_size(args...);
template <typename Arg>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size_one(const Arg& arg) {
  Serializer<std::decay_t<Arg>> serializer;
  return serializer.size(arg);
}

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* end, const T1& value,
                                                                  const Ts&... args) {
    Serializer serializer;
    dest = serializer.serialize(dest, end, value);
    return serialize_impl<N - 1, Ts...>::serialize(dest, end, args...);
template <typename Arg>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize_one(uint8_t* dest, uint8_t* end, const Arg& arg) {
  Serializer<std::decay_t<Arg>> serializer;
  return serializer.serialize(dest, end, arg);
}

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* end,
                                                                          T1& value, Ts&... args) {
    Serializer serializer;
    src = serializer.deserialize(src, end, value);
    return serialize_impl<N - 1, Ts...>::deserialize(src, end, args...);
template <typename Arg>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize_one(const uint8_t* src, const uint8_t* end, Arg& arg) {
  Serializer<std::decay_t<Arg>> serializer;
  return serializer.deserialize(src, end, arg);
}
};

// Base case.
template <>
struct serialize_impl<0> {
  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size() { return 0; }

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* /*end*/) { return dest; }

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* /*end*/) {
    return src;
  }
};

}  // namespace internal

@@ -174,7 +151,10 @@ struct serialize_impl<0> {
 */
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size(const Args&... args) {
  return internal::serialize_impl<sizeof...(args), Args...>::serialize_size(args...);
  size_t size = 0;
  int unused[] = {0, (size += internal::serialize_size_one(args), 0)...};
  EIGEN_UNUSED_VARIABLE(unused);
  return size;
}

/**
@@ -187,7 +167,10 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size(const Args&... args)
 */
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* end, const Args&... args) {
  return internal::serialize_impl<sizeof...(args), Args...>::serialize(dest, end, args...);
  EIGEN_UNUSED_VARIABLE(end);
  int unused[] = {0, (dest = internal::serialize_one(dest, end, args), 0)...};
  EIGEN_UNUSED_VARIABLE(unused);
  return dest;
}

/**
@@ -201,7 +184,10 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t*
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* end,
                                                                 Args&... args) {
  return internal::serialize_impl<sizeof...(args), Args...>::deserialize(src, end, args...);
  EIGEN_UNUSED_VARIABLE(end);
  int unused[] = {0, (src = internal::deserialize_one(src, end, args), 0)...};
  EIGEN_UNUSED_VARIABLE(unused);
  return src;
}

}  // namespace Eigen
+24 −0
Original line number Diff line number Diff line
@@ -43,6 +43,13 @@ struct dummy_c {};
struct dummy_d {};
struct dummy_e {};

struct widening_sum_op {
  template <typename A, typename B>
  EIGEN_DEVICE_FUNC constexpr static long long run(A a, B b) {
    return static_cast<long long>(a) + static_cast<long long>(b);
  }
};

// dummy operation for testing apply
template <typename A, typename B>
struct dummy_op;
@@ -221,11 +228,28 @@ static void test_arg_reductions() {
static void test_array_reductions() {
  array<int, 6> a{{4, 8, 15, 16, 23, 42}};
  array<int, 6> b{{42, 23, 16, 15, 8, 4}};
  array<unsigned char, 0> empty{};
  array<unsigned char, 1> singleton{{200}};
  array<unsigned char, 2> narrow{{200, 100}};
  array<unsigned char, 3> custom{{200, 100, 50}};

  VERIFY_IS_EQUAL((array_sum(a)), 108);
  VERIFY_IS_EQUAL((array_sum(b)), 108);
  VERIFY_IS_EQUAL((array_prod(a)), 7418880);
  VERIFY_IS_EQUAL((array_prod(b)), 7418880);
  VERIFY((std::is_same<decltype(array_sum(empty)), unsigned char>::value));
  VERIFY((std::is_same<decltype(array_sum(singleton)), unsigned char>::value));
  VERIFY((std::is_same<decltype(array_sum(narrow)), int>::value));
  VERIFY((std::is_same<decltype(array_prod(narrow)), int>::value));
  VERIFY_IS_EQUAL((array_sum(empty)), 0);
  VERIFY_IS_EQUAL((array_prod(empty)), 1);
  VERIFY_IS_EQUAL((array_sum(singleton)), 200);
  VERIFY_IS_EQUAL((array_prod(singleton)), 200);
  VERIFY_IS_EQUAL((array_sum(narrow)), 300);
  VERIFY_IS_EQUAL((array_prod(narrow)), 20000);
  VERIFY(
      (std::is_same<decltype(array_reduce<widening_sum_op>(custom, static_cast<unsigned char>(0))), long long>::value));
  VERIFY_IS_EQUAL((array_reduce<widening_sum_op>(custom, static_cast<unsigned char>(0))), 350);
}

EIGEN_DECLARE_TEST(meta) {
Loading