// Copyright 2015-2017 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 namespace boost { namespace histogram { template adaptive_storage prepare(std::size_t n = 1) { adaptive_storage s(n); s.increase(0); const auto tmax = std::numeric_limits::max(); while (s.value(0) < 0.1 * tmax) { s.add(0, s.value(0)); } return s; } template <> adaptive_storage prepare(std::size_t n) { adaptive_storage s(n); return s; } template <> adaptive_storage prepare(std::size_t n) { adaptive_storage s(n); s.increase_by_weight(0, 1.0); return s; } template <> adaptive_storage prepare(std::size_t n) { adaptive_storage s(n); s.increase(0); auto tmax = static_cast(std::numeric_limits::max()); tmax *= 2.0; while (s.value(0) < tmax) { assert(s.value(0) != 0); s.add(0, s.value(0)); } return s; } } // namespace histogram namespace python { // cheating to get access class access { public: template static histogram::adaptive_storage set_value(std::size_t n, T x) { histogram::adaptive_storage s = histogram::prepare(n); get>(s.buffer_)[0] = x; return s; } }; } // namespace python namespace histogram { template void copy_impl() { const auto b = prepare(1); auto a(b); BOOST_TEST(a == b); a.increase(0); BOOST_TEST(!(a == b)); a = b; BOOST_TEST(a == b); a.increase(0); BOOST_TEST(!(a == b)); a = b; a = prepare(2); BOOST_TEST(!(a == b)); a = b; BOOST_TEST(a == b); } template void serialization_impl() { const auto a = python::access::set_value(1, T(1)); std::ostringstream os; std::string buf; { std::ostringstream os; boost::archive::text_oarchive oa(os); oa << a; buf = os.str(); } adaptive_storage b; BOOST_TEST(!(a == b)); { std::istringstream is(buf); boost::archive::text_iarchive ia(is); ia >> b; } BOOST_TEST(a == b); } template <> void serialization_impl() { adaptive_storage a(std::size_t(1)); std::ostringstream os; std::string buf; { std::ostringstream os; boost::archive::text_oarchive oa(os); oa << a; buf = os.str(); } adaptive_storage b; BOOST_TEST(!(a == b)); { std::istringstream is(buf); boost::archive::text_iarchive ia(is); ia >> b; } BOOST_TEST(a == b); } template void equal_impl() { adaptive_storage a(std::size_t(1)); auto b = python::access::set_value(1, T(0)); BOOST_TEST_EQ(a.value(0), 0.0); BOOST_TEST_EQ(a.variance(0), 0.0); BOOST_TEST(a == b); b.increase(0); BOOST_TEST(!(a == b)); array_storage c(std::size_t(1)); auto d = python::access::set_value(1, T(0)); BOOST_TEST(c == d); c.increase(0); BOOST_TEST(!(c == d)); } template <> void equal_impl() { adaptive_storage a(std::size_t(1)); auto b = python::access::set_value(1, uint8_t(0)); auto c = python::access::set_value(2, uint8_t(0)); auto d = array_storage(std::size_t(1)); BOOST_TEST_EQ(a.value(0), 0.0); BOOST_TEST_EQ(a.variance(0), 0.0); BOOST_TEST(a == b); BOOST_TEST(b == a); BOOST_TEST(a == d); BOOST_TEST(d == a); BOOST_TEST(!(a == c)); BOOST_TEST(!(c == a)); b.increase(0); BOOST_TEST(!(a == b)); BOOST_TEST(!(b == a)); d.increase(0); BOOST_TEST(!(a == d)); BOOST_TEST(!(d == a)); } template void increase_and_grow_impl() { auto tmax = std::numeric_limits::max(); auto s = python::access::set_value(2, tmax - 1); auto n = s; auto n2 = s; n.increase(0); n.increase(0); adaptive_storage x(std::size_t(2)); x.increase(0); n2.add(0, x.value(0)); n2.add(0, x.value(0)); double v = tmax; ++v; BOOST_TEST_EQ(n.value(0), v); BOOST_TEST_EQ(n2.value(0), v); BOOST_TEST_EQ(n.value(1), 0.0); BOOST_TEST_EQ(n2.value(1), 0.0); } template <> void increase_and_grow_impl() { adaptive_storage s(std::size_t(2)); s.increase(0); BOOST_TEST_EQ(s.value(0), 1.0); BOOST_TEST_EQ(s.value(1), 0.0); } template void convert_array_storage_impl() { const auto aref = python::access::set_value(1, T(0)); array_storage s(std::size_t(1)); s.increase(0); auto a = aref; a = s; BOOST_TEST_EQ(a.value(0), 1.0); BOOST_TEST(a == s); a.increase(0); BOOST_TEST(!(a == s)); adaptive_storage b(s); BOOST_TEST_EQ(b.value(0), 1.0); BOOST_TEST(b == s); b.increase(0); BOOST_TEST(!(b == s)); auto c = aref; c.add(0, s.value(0)); BOOST_TEST_EQ(c.value(0), 1.0); BOOST_TEST(c == s); BOOST_TEST(s == c); array_storage t(std::size_t(1)); t.increase(0); while (t.value(0) < 1e20) t.add(0, t.value(0)); auto d = aref; d = t; BOOST_TEST(d == t); auto e = aref; e = s; BOOST_TEST_EQ(e.value(0), 1.0); BOOST_TEST(e == s); e.increase(0); BOOST_TEST(!(e == s)); adaptive_storage f(s); BOOST_TEST_EQ(f.value(0), 1.0); BOOST_TEST(f == s); f.increase(0); BOOST_TEST(!(f == s)); auto g = aref; g.add(0, s.value(0)); BOOST_TEST_EQ(g.value(0), 1.0); BOOST_TEST(g == s); BOOST_TEST(s == g); array_storage u(std::size_t(2)); u.increase(0); auto h = aref; BOOST_TEST(!(h == u)); h = u; BOOST_TEST(h == u); } template <> void convert_array_storage_impl() { const auto aref = adaptive_storage(std::size_t(1)); BOOST_TEST_EQ(aref.value(0), 0.0); array_storage s(std::size_t(1)); s.increase(0); auto a = aref; a = s; BOOST_TEST_EQ(a.value(0), 1.0); BOOST_TEST(a == s); a.increase(0); BOOST_TEST(!(a == s)); auto c = aref; c.add(0, s.value(0)); BOOST_TEST_EQ(c.value(0), 1.0); BOOST_TEST(c == s); BOOST_TEST(s == c); array_storage t(std::size_t(2)); t.increase(0); auto d = aref; BOOST_TEST(!(d == t)); } } // namespace histogram } // namespace boost int main() { using namespace boost::histogram; // low-level tools { uint8_t c = 0; BOOST_TEST_EQ(detail::safe_increase(c), true); BOOST_TEST_EQ(c, 1); c = 255; BOOST_TEST_EQ(detail::safe_increase(c), false); BOOST_TEST_EQ(c, 255); BOOST_TEST_EQ(detail::safe_assign(c, 255), true); BOOST_TEST_EQ(detail::safe_assign(c, 256), false); BOOST_TEST_EQ(c, 255); c = 0; BOOST_TEST_EQ(detail::safe_radd(c, 255), true); BOOST_TEST_EQ(c, 255); c = 1; BOOST_TEST_EQ(detail::safe_radd(c, 255), false); BOOST_TEST_EQ(c, 1); c = 255; BOOST_TEST_EQ(detail::safe_radd(c, 1), false); BOOST_TEST_EQ(c, 255); } // empty state { adaptive_storage a; BOOST_TEST_EQ(a.size(), 0); } // copy { copy_impl(); copy_impl(); copy_impl(); copy_impl(); copy_impl(); copy_impl(); copy_impl(); } // equal_operator { equal_impl(); equal_impl(); equal_impl(); equal_impl(); equal_impl(); equal_impl(); equal_impl(); } // increase_and_grow { increase_and_grow_impl(); increase_and_grow_impl(); increase_and_grow_impl(); increase_and_grow_impl(); increase_and_grow_impl(); // only increase for mp_int auto a = boost::python::access::set_value(2, detail::mp_int(1)); BOOST_TEST_EQ(a.value(0), 1.0); BOOST_TEST_EQ(a.value(1), 0.0); a.increase(0); BOOST_TEST_EQ(a.value(0), 2.0); BOOST_TEST_EQ(a.value(1), 0.0); } // add_and_grow { adaptive_storage a(std::size_t(1)); a.increase(0); double x = 1.0; adaptive_storage y(std::size_t(1)); BOOST_TEST_EQ(y.value(0), 0.0); a.add(0, y.value(0)); BOOST_TEST_EQ(a.value(0), x); for (unsigned i = 0; i < 80; ++i) { a.add(0, a.value(0)); x += x; adaptive_storage b(std::size_t(1)); b.add(0, a.value(0)); BOOST_TEST_EQ(a.value(0), x); BOOST_TEST_EQ(a.variance(0), x); BOOST_TEST_EQ(b.value(0), x); BOOST_TEST_EQ(b.variance(0), x); b.increase_by_weight(0, 0.0); BOOST_TEST_EQ(b.value(0), x); BOOST_TEST_EQ(b.variance(0), x); adaptive_storage c(std::size_t(1)); c.increase_by_weight(0, a.value(0)); BOOST_TEST_EQ(c.value(0), x); BOOST_TEST_EQ(c.variance(0), x * x); } } // multiply { adaptive_storage a(std::size_t(2)); a.increase(0); a *= 3; BOOST_TEST_EQ(a.value(0), 3); BOOST_TEST_EQ(a.variance(0), 9); BOOST_TEST_EQ(a.value(1), 0); BOOST_TEST_EQ(a.variance(1), 0); a.add(1, 2.0, 5.0); BOOST_TEST_EQ(a.value(0), 3); BOOST_TEST_EQ(a.variance(0), 9); BOOST_TEST_EQ(a.value(1), 2); BOOST_TEST_EQ(a.variance(1), 5); a *= 3; BOOST_TEST_EQ(a.value(0), 9); BOOST_TEST_EQ(a.variance(0), 81); BOOST_TEST_EQ(a.value(1), 6); BOOST_TEST_EQ(a.variance(1), 45); } // convert_array_storage { convert_array_storage_impl(); convert_array_storage_impl(); convert_array_storage_impl(); convert_array_storage_impl(); convert_array_storage_impl(); convert_array_storage_impl(); convert_array_storage_impl(); } // serialization_test { serialization_impl(); serialization_impl(); serialization_impl(); serialization_impl(); serialization_impl(); serialization_impl(); serialization_impl(); } return boost::report_errors(); }