diff --git a/CMakeLists.txt b/CMakeLists.txt index 42189a03..07400758 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ endfunction() compiled_test(test/adaptive_storage_test.cpp) compiled_test(test/algorithm_project_test.cpp) +compiled_test(test/algorithm_sum_test.cpp) compiled_test(test/axis_regular_test.cpp) compiled_test(test/axis_circular_test.cpp) compiled_test(test/axis_variable_test.cpp) diff --git a/include/boost/histogram/algorithm/sum.hpp b/include/boost/histogram/algorithm/sum.hpp new file mode 100644 index 00000000..ecdd1ce5 --- /dev/null +++ b/include/boost/histogram/algorithm/sum.hpp @@ -0,0 +1,27 @@ +// Copyright 2018 Hans Dembinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_HISTOGRAM_ALGORITHM_SUM_HPP +#define BOOST_HISTOGRAM_ALGORITHM_SUM_HPP + +#include +#include +#include + +namespace boost { +namespace histogram { +namespace algorithm { +template +typename histogram::value_type sum(const histogram& h) { + using T = typename histogram::value_type; + return std::accumulate(h.begin(), h.end(), + std::conditional_t::value, double, T>()); +} +} // namespace algorithm +} // namespace histogram +} // namespace boost + +#endif diff --git a/include/boost/histogram/detail/meta.hpp b/include/boost/histogram/detail/meta.hpp index 125fb3f2..ce30566d 100644 --- a/include/boost/histogram/detail/meta.hpp +++ b/include/boost/histogram/detail/meta.hpp @@ -227,28 +227,25 @@ using is_sample = is_sample_impl>; template (), ++std::declval())> struct requires_iterator {}; -template , void>> +template >, void>> struct requires_iterable {}; -template , void>> +template >, void>> struct requires_tuple {}; -template , void>> +template >, void>> struct requires_axis {}; -template , void>> +template >, void>> struct requires_axis_or_axis_variant {}; -template , void>> +template >, void>> struct requires_axis_vector {}; -template , void>> -struct requires_same {}; - -template , void>> +template >, void>> struct requires_transform {}; -template , void>> +template >, void>> struct requires_storage {}; } // namespace detail diff --git a/test/algorithm_project_test.cpp b/test/algorithm_project_test.cpp index 2547ffa2..07422702 100644 --- a/test/algorithm_project_test.cpp +++ b/test/algorithm_project_test.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,7 @@ using namespace boost::histogram; using namespace boost::histogram::literals; // to get _c suffix -using boost::histogram::algorithm::project; +using namespace boost::histogram::algorithm; template void run_tests() { diff --git a/test/algorithm_sum_test.cpp b/test/algorithm_sum_test.cpp new file mode 100644 index 00000000..2e8f2438 --- /dev/null +++ b/test/algorithm_sum_test.cpp @@ -0,0 +1,46 @@ +// Copyright 2018 Hans Dembinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "utility_histogram.hpp" + +using namespace boost::histogram; +using namespace boost::histogram::literals; // to get _c suffix +using boost::histogram::algorithm::sum; + +template +void run_tests() { + auto ax = axis::integer<>(0, 100); + + auto h1 = make(Tag(), ax); + for (unsigned i = 0; i < 100; ++i) h1(i); + BOOST_TEST_EQ(sum(h1), 100); + + auto h2 = make_s(Tag(), std::vector(), ax, ax); + for (unsigned i = 0; i < 100; ++i) + for (unsigned j = 0; j < 100; ++j) h2(i, j); + + BOOST_TEST_EQ(sum(h2), 100000); + + auto h3 = make_s(Tag(), std::array(), ax); + for (unsigned i = 0; i < 100; ++i) h3(i); + + BOOST_TEST_EQ(sum(h3), 100); + + auto h4 = make_s(Tag(), std::unordered_map(), ax); + for (unsigned i = 0; i < 100; ++i) h3(i); + + BOOST_TEST_EQ(sum(h3), 100); +} + +int main() { + run_tests(); + run_tests(); + + return boost::report_errors(); +} diff --git a/test/histogram_test.cpp b/test/histogram_test.cpp index 84fe615c..61ddd0a3 100644 --- a/test/histogram_test.cpp +++ b/test/histogram_test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -133,12 +134,12 @@ void run_tests() { h(0, 0); const auto href = h; decltype(h) h2(std::move(h)); - BOOST_TEST_EQ(sum(h), 0); + BOOST_TEST_EQ(algorithm::sum(h), 0); BOOST_TEST_EQ(h.size(), 0); BOOST_TEST_EQ(h2, href); decltype(h) h3; h3 = std::move(h2); - BOOST_TEST_EQ(sum(h2), 0); + BOOST_TEST_EQ(algorithm::sum(h2), 0); BOOST_TEST_EQ(h2.size(), 0); BOOST_TEST_EQ(h3, href); } @@ -224,7 +225,7 @@ void run_tests() { BOOST_TEST_EQ(h.rank(), 1); BOOST_TEST_EQ(h.axis().size(), 2); - BOOST_TEST_EQ(sum(h), 4); + BOOST_TEST_EQ(algorithm::sum(h), 4); BOOST_TEST_EQ(h.at(-1), 1); BOOST_TEST_EQ(h.at(0), 2); @@ -242,7 +243,7 @@ void run_tests() { BOOST_TEST_EQ(h.rank(), 1); BOOST_TEST_EQ(h.axis().size(), 2); - BOOST_TEST_EQ(sum(h), 2); + BOOST_TEST_EQ(algorithm::sum(h), 2); BOOST_TEST_EQ(h.at(0), 2); BOOST_TEST_EQ(h.at(1), 0); @@ -258,7 +259,7 @@ void run_tests() { BOOST_TEST_EQ(h.rank(), 1); BOOST_TEST_EQ(h.axis().size(), 2); - BOOST_TEST_EQ(sum(h), 4); + BOOST_TEST_EQ(algorithm::sum(h), 4); BOOST_TEST_EQ(h.at(0), 1); BOOST_TEST_EQ(h.at(1), 1); @@ -274,8 +275,8 @@ void run_tests() { h(1); h(weight(2), 2); - BOOST_TEST_EQ(sum(h).value(), 5.5); - BOOST_TEST_EQ(sum(h).variance(), 7.25); + BOOST_TEST_EQ(algorithm::sum(h).value(), 5.5); + BOOST_TEST_EQ(algorithm::sum(h).variance(), 7.25); BOOST_TEST_EQ(h[-1].value(), 1); BOOST_TEST_EQ(h[-1].variance(), 1); @@ -321,7 +322,7 @@ void run_tests() { BOOST_TEST_EQ(h.rank(), 2); BOOST_TEST_EQ(h.axis(0_c).size(), 2); BOOST_TEST_EQ(h.axis(1_c).size(), 3); - BOOST_TEST_EQ(sum(h), 3); + BOOST_TEST_EQ(algorithm::sum(h), 3); BOOST_TEST_EQ(h.at(-1, 0), 0); BOOST_TEST_EQ(h.at(-1, 1), 1); @@ -350,8 +351,8 @@ void run_tests() { h(weight(5), -1, -10); // is ignored h(weight(7), -10, 0); // -> -1, 1 - BOOST_TEST_EQ(sum(h).value(), 18); - BOOST_TEST_EQ(sum(h).variance(), 150); + BOOST_TEST_EQ(algorithm::sum(h).value(), 18); + BOOST_TEST_EQ(algorithm::sum(h).variance(), 150); BOOST_TEST_EQ(h.at(-1, 0).value(), 0); BOOST_TEST_EQ(h.at(-1, 1).value(), 7); @@ -498,7 +499,7 @@ void run_tests() { BOOST_TEST_EQ(h.at(0), 1); BOOST_TEST_EQ(h.at(1), 1); BOOST_TEST_EQ(h.at(2), 1); - BOOST_TEST_EQ(sum(h), 3); + BOOST_TEST_EQ(algorithm::sum(h), 3); auto a = std::vector(); std::partial_sum(h.begin(), h.end(), std::back_inserter(a)); @@ -562,11 +563,11 @@ void run_tests() { h(1); BOOST_TEST_EQ(h.at(0), 1); BOOST_TEST_EQ(h.at(1), 1); - BOOST_TEST_EQ(sum(h), 2); + BOOST_TEST_EQ(algorithm::sum(h), 2); h.reset(); BOOST_TEST_EQ(h.at(0), 0); BOOST_TEST_EQ(h.at(1), 0); - BOOST_TEST_EQ(sum(h), 0); + BOOST_TEST_EQ(algorithm::sum(h), 0); } // custom axes @@ -696,7 +697,7 @@ void run_tests() { ++it; BOOST_TEST(it == h.end()); - auto v = sum(h); + auto v = algorithm::sum(h); BOOST_TEST_EQ(v.value(), 4); BOOST_TEST_EQ(v.variance(), 6); } diff --git a/test/utility_histogram.hpp b/test/utility_histogram.hpp index 78970eb6..965062cf 100644 --- a/test/utility_histogram.hpp +++ b/test/utility_histogram.hpp @@ -17,10 +17,6 @@ namespace boost { namespace histogram { -template -auto sum(const Histogram& h) { - return std::accumulate(h.begin(), h.end(), typename Histogram::value_type(0)); -} template auto make_axis_vector(Ts&&... ts) {