// Copyright 2018-2019 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 #include #include #include #include #include #include #include #include #include #include #include #include "throw_exception.hpp" #include "utility_histogram.hpp" using namespace boost::histogram; struct modified_axis : public axis::integer<> { using integer::integer; // inherit ctors of base // customization point: convert argument and call base class auto index(const char* s) const { return integer::index(std::atoi(s)); } }; struct minimal { auto index(int x) const { return static_cast(x % 2); } auto size() const { return axis::index_type{2}; } }; struct axis2d { auto index(const std::tuple& x) const { return axis::index_type{std::get<0>(x) == 1 && std::get<1>(x) == 2}; } auto size() const { return axis::index_type{2}; } }; class axis2d_growing { public: auto index(std::tuple xy) const { const auto x = std::get<0>(xy); const auto y = std::get<1>(xy); const auto r = std::sqrt(x * x + y * y); return std::min(static_cast(r), size()); } auto update(std::tuple xy) { const auto x = std::get<0>(xy); const auto y = std::get<1>(xy); const auto r = std::sqrt(x * x + y * y); const auto n = static_cast(r); const auto old = size_; if (n >= size_) size_ = n + 1; return std::make_pair(n, old - size_); } axis::index_type size() const { return size_; } private: axis::index_type size_ = 0; }; template void run_tests() { // one 2d axis { auto h = make(Tag(), axis2d()); h(1, 2); // ok, forwards 2d tuple to axis h(std::make_tuple(1, 2)); // also ok, forwards 2d tuple to axis BOOST_TEST_THROWS(h(1), std::invalid_argument); BOOST_TEST_THROWS(h(1, 2, 3), std::invalid_argument); BOOST_TEST_EQ(h.at(0), 0); // ok, bin access is still 1d BOOST_TEST_EQ(h[std::make_tuple(1)], 2); // also works with weights h(1, 2, weight(2)); h(std::make_tuple(weight(3), 1, 2)); BOOST_TEST_EQ(h.at(0), 0); BOOST_TEST_EQ(h.at(1), 7); auto h2 = make_s(Tag(), profile_storage(), axis2d()); h2(1, 2, sample(2)); BOOST_TEST_EQ(h2[1].count(), 1); BOOST_TEST_EQ(h2[1].value(), 2); auto h3 = make_s(Tag(), weighted_profile_storage(), axis2d()); h3(1, 2, weight(3), sample(2)); BOOST_TEST_EQ(h3[1].sum_of_weights(), 3); BOOST_TEST_EQ(h3[1].value(), 2); } // several axes, one 2d { auto h = make(Tag(), modified_axis(0, 3), minimal(), axis2d()); h("0", 1, std::make_tuple(1.0, 2.0)); h("1", 2, std::make_tuple(2.0, 1.0)); BOOST_TEST_EQ(h.rank(), 3); BOOST_TEST_EQ(h.at(0, 0, 0), 0); BOOST_TEST_EQ(h.at(0, 1, 1), 1); BOOST_TEST_EQ(h.at(1, 0, 0), 1); } // growing axis { auto h = make_s(Tag{}, std::vector{}, axis2d_growing{}); BOOST_TEST_EQ(h.size(), 0); h(0, 0); BOOST_TEST_EQ(h.size(), 1); h(1, 0); h(0, 1); BOOST_TEST_EQ(h.size(), 2); h(10, 0); BOOST_TEST_EQ(h.size(), 11); BOOST_TEST_EQ(h[0], 1); BOOST_TEST_EQ(h[1], 2); BOOST_TEST_EQ(h[10], 1); BOOST_TEST_THROWS(h(0), std::invalid_argument); } } int main() { run_tests(); run_tests(); return boost::report_errors(); }