// 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 #include #include #include "is_close.hpp" #include "utility_allocator.hpp" using namespace boost::histogram; template void tests() { // ctor, copy, move { storage_adaptor a; a.reset(2); storage_adaptor b(a); storage_adaptor c; c = a; BOOST_TEST_EQ(a.size(), 2); BOOST_TEST_EQ(b.size(), 2); BOOST_TEST_EQ(c.size(), 2); storage_adaptor d(std::move(a)); BOOST_TEST_EQ(d.size(), 2); storage_adaptor e; e = std::move(d); BOOST_TEST_EQ(e.size(), 2); const auto t = T(); storage_adaptor g(t); // tests converting ctor } // increment, add, sub, set, reset { storage_adaptor a; a.reset(1); ++a[0]; ++a[0]; BOOST_TEST_EQ(a[0], 2); a.reset(2); BOOST_TEST_EQ(a.size(), 2); ++a[0]; a[0] += 2; a[1] += 5; BOOST_TEST_EQ(a[0], 3); BOOST_TEST_EQ(a[1], 5); a[0] -= 2; a[1] -= 5; BOOST_TEST_EQ(a[0], 1); BOOST_TEST_EQ(a[1], 0); a[1] = 9; BOOST_TEST_EQ(a[0], 1); BOOST_TEST_EQ(a[1], 9); a.reset(0); BOOST_TEST_EQ(a.size(), 0); } // copy { storage_adaptor a; a.reset(1); ++a[0]; decltype(a) b; b.reset(2); BOOST_TEST(!(a == b)); b = a; BOOST_TEST(a == b); BOOST_TEST_EQ(b.size(), 1); BOOST_TEST_EQ(b[0], 1); decltype(a) c(a); BOOST_TEST(a == c); BOOST_TEST_EQ(c.size(), 1); BOOST_TEST_EQ(c[0], 1); } // move { storage_adaptor a; a.reset(1); ++a[0]; decltype(a) b; BOOST_TEST(!(a == b)); b = std::move(a); BOOST_TEST_EQ(b.size(), 1); BOOST_TEST_EQ(b[0], 1); decltype(a) c(std::move(b)); BOOST_TEST_EQ(c.size(), 1); BOOST_TEST_EQ(c[0], 1); } } template void mixed_tests() { // comparison { A a, b; a.reset(1); b.reset(1); B c, d; c.reset(1); d.reset(2); ++a[0]; ++b[0]; c[0] += 2; d[0] = 3; d[1] = 5; BOOST_TEST_EQ(a[0], 1); BOOST_TEST_EQ(b[0], 1); BOOST_TEST_EQ(c[0], 2); BOOST_TEST_EQ(d[0], 3); BOOST_TEST_EQ(d[1], 5); BOOST_TEST(a == a); BOOST_TEST(a == b); BOOST_TEST(!(a == c)); BOOST_TEST(!(a == d)); } // ctor, copy, move { A a; a.reset(2); ++a[1]; B b(a); B c; c = a; BOOST_TEST_EQ(c[0], 0); BOOST_TEST_EQ(c[1], 1); B d(std::move(a)); B e; e = std::move(d); BOOST_TEST_EQ(e[0], 0); BOOST_TEST_EQ(e[1], 1); } } int main() { tests>(); tests>(); tests>(); tests>(); tests>(); mixed_tests>, storage_adaptor>>(); mixed_tests, storage_adaptor>>(); mixed_tests>, unlimited_storage<>>(); // with accumulators::weighted_sum { auto a = storage_adaptor>>(); a.reset(1); ++a[0]; a[0] += 1; a[0] += 2; a[0] += accumulators::weighted_sum(1, 0); BOOST_TEST_EQ(a[0].value(), 5); BOOST_TEST_EQ(a[0].variance(), 6); } // with accumulators::weighted_mean { auto a = storage_adaptor>>(); a.reset(1); a[0](/* sample */ 1); a[0](/* weight */ 2, /* sample */ 2); a[0] += accumulators::weighted_mean<>(1, 0, 0, 0); BOOST_TEST_EQ(a[0].sum_of_weights(), 4); BOOST_TEST_IS_CLOSE(a[0].value(), 1.25, 1e-3); BOOST_TEST_IS_CLOSE(a[0].variance(), 0.242, 1e-3); } // exceeding array capacity { auto a = storage_adaptor>(); a.reset(10); // should not throw BOOST_TEST_THROWS(a.reset(11), std::runtime_error); } // test sparsity of map backend { tracing_allocator_db db; tracing_allocator alloc(db); using map = std::map, tracing_allocator>>; using A = storage_adaptor; auto a = A(map(alloc)); // MSVC implementation allocates some structures for debugging const auto baseline = db.sum.first; a.reset(10); BOOST_TEST_EQ(db.sum.first, baseline); // nothing allocated yet // queries do not allocate BOOST_TEST_EQ(a[0], 0); BOOST_TEST_EQ(a[9], 0); BOOST_TEST_EQ(db.sum.first, baseline); ++a[5]; // causes one allocation BOOST_TEST_EQ(a[5], 1); BOOST_TEST_EQ(db.sum.first, baseline + 1); a[4] += 2; // causes one allocation BOOST_TEST_EQ(a[4], 2); BOOST_TEST_EQ(db.sum.first, baseline + 2); const auto baseline_dealloc = db.sum.second; a[4] = 0; // causes one deallocation BOOST_TEST_EQ(db.sum.second, baseline_dealloc + 1); auto b = storage_adaptor>(); b.reset(5); ++b[2]; a = b; // only one new allocation for non-zero value BOOST_TEST_EQ(db.sum.first, baseline + 3); } return boost::report_errors(); }