CarpetX: a Cactus driver for the Einstein Toolkit based on AMReX
#ifndef SUM_HXX
#define SUM_HXX

#include <fixmath.hxx> // include this before <cctk.h>
#include <cctk.h>

#include <functional>

#ifdef CCTK_DEBUG
#define ARITH_INLINE
#else
#define ARITH_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE
#endif

namespace Arith {
using namespace std;

template <int D, typename F>
constexpr ARITH_INLINE remove_cv_t<remove_reference_t<result_of_t<F(int)> > >
sum(F f) {
  using R = remove_cv_t<remove_reference_t<result_of_t<F(int)> > >;
  R s{0};
  for (int x = 0; x < D; ++x)
    s += f(x);
  return s;
}

template <int D, typename F>
constexpr
    ARITH_INLINE remove_cv_t<remove_reference_t<result_of_t<F(int, int)> > >
    sum(F f) {
  using R = remove_cv_t<remove_reference_t<result_of_t<F(int, int)> > >;
  R s{0};
  for (int x = 0; x < D; ++x)
    for (int y = 0; y < D; ++y)
      s += f(x, y);
  return s;
}

template <int D, typename F>
constexpr ARITH_INLINE
    remove_cv_t<remove_reference_t<result_of_t<F(int, int, int)> > >
    sum(F f) {
  using R = remove_cv_t<remove_reference_t<result_of_t<F(int, int, int)> > >;
  R s{0};
  for (int x = 0; x < D; ++x)
    for (int y = 0; y < D; ++y)
      for (int z = 0; z < D; ++z)
        s += f(x, y, z);
  return s;
}

} // namespace Arith

#undef ARITH_INLINE

#endif