sum.hpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2018 Hans Dembinski
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_HISTOGRAM_ALGORITHM_SUM_HPP
  7. #define BOOST_HISTOGRAM_ALGORITHM_SUM_HPP
  8. #include <boost/histogram/accumulators/sum.hpp>
  9. #include <boost/histogram/fwd.hpp>
  10. #include <boost/histogram/indexed.hpp>
  11. #include <boost/mp11/utility.hpp>
  12. #include <type_traits>
  13. namespace boost {
  14. namespace histogram {
  15. namespace algorithm {
  16. /** Compute the sum over all histogram cells (underflow/overflow included by default).
  17. The implementation favors accuracy and protection against overflow over speed. If the
  18. value type of the histogram is an integral or floating point type,
  19. accumulators::sum<double> is used to compute the sum, else the original value type is
  20. used. Compilation fails, if the value type does not support operator+=. The return type
  21. is double if the value type of the histogram is integral or floating point, and the
  22. original value type otherwise.
  23. If you need a different trade-off, you can write your own loop or use `std::accumulate`:
  24. ```
  25. // iterate over all bins
  26. auto sum_all = std::accumulate(hist.begin(), hist.end(), 0.0);
  27. // skip underflow/overflow bins
  28. double sum = 0;
  29. for (auto&& x : indexed(hist))
  30. sum += *x; // dereference accessor
  31. // or:
  32. // auto ind = boost::histogram::indexed(hist);
  33. // auto sum = std::accumulate(ind.begin(), ind.end(), 0.0);
  34. ```
  35. @returns accumulator type or double
  36. @param hist Const reference to the histogram.
  37. @param cov Iterate over all or only inner bins (optional, default: all).
  38. */
  39. template <class A, class S>
  40. auto sum(const histogram<A, S>& hist, const coverage cov = coverage::all) {
  41. using T = typename histogram<A, S>::value_type;
  42. // T is arithmetic, compute sum accurately with high dynamic range
  43. using sum_type = mp11::mp_if<std::is_arithmetic<T>, accumulators::sum<double>, T>;
  44. sum_type sum;
  45. if (cov == coverage::all)
  46. for (auto&& x : hist) sum += x;
  47. else
  48. // sum += x also works if sum_type::operator+=(const sum_type&) exists
  49. for (auto&& x : indexed(hist)) sum += *x;
  50. using R = mp11::mp_if<std::is_arithmetic<T>, double, T>;
  51. return static_cast<R>(sum);
  52. }
  53. } // namespace algorithm
  54. } // namespace histogram
  55. } // namespace boost
  56. #endif