wip, axis_test passes

This commit is contained in:
Hans Dembinski
2018-10-21 22:23:34 +02:00
parent 7822c87f4f
commit c02e7b0f22
22 changed files with 553 additions and 447 deletions

View File

@@ -12,9 +12,11 @@
#include <boost/histogram/axis/types.hpp>
#include <boost/histogram/detail/axes.hpp>
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/histogram/detail/meta.hpp>
#include <limits>
#include <sstream>
#include <string>
#include <type_traits>
#include "utility.hpp"
using namespace boost::histogram;
@@ -36,6 +38,33 @@ void test_axis_iterator(const Axis& a, int begin, int end) {
}
}
// quantity with unit for testing
template <typename Unit>
struct quantity {
double value;
};
struct length {
double value;
};
auto meter = length{1.0};
template <typename Unit>
double operator/(const quantity<Unit>& a, const Unit& u) {
return a.value / u.value;
}
template <typename Unit>
quantity<Unit> operator*(double x, const Unit& u) {
return quantity<Unit>{x * u.value};
}
template <typename Unit>
quantity<Unit> operator-(const quantity<Unit>& a, const quantity<Unit>& b) {
return quantity<Unit>{a.value - b.value};
}
int main() {
// bad_ctors
{
@@ -79,6 +108,19 @@ int main() {
BOOST_TEST_EQ(a(std::numeric_limits<double>::quiet_NaN()), 4);
}
// regular axis with inverted range
{
axis::regular<> a(2, 1, -1);
BOOST_TEST_EQ(a[0].lower(), 1);
BOOST_TEST_EQ(a[1].lower(), 0);
BOOST_TEST_EQ(a[2].lower(), -1);
BOOST_TEST_EQ(a(2), -1);
BOOST_TEST_EQ(a(1), 0);
BOOST_TEST_EQ(a(0), 1);
BOOST_TEST_EQ(a(-1), 2);
BOOST_TEST_EQ(a(-2), 2);
}
// axis::regular with log transform
{
axis::regular<axis::transform::log<>> b{2, 1e0, 1e2};
@@ -118,6 +160,27 @@ int main() {
BOOST_TEST_EQ(b(std::numeric_limits<double>::infinity()), 2);
}
// axis::regular with quantity transform
{
axis::regular<axis::transform::quantity<quantity<length>, length>> b{
2, 0*meter, 2*meter, {}, axis::option_type::underflow_and_overflow, meter
};
BOOST_TEST_EQ(b[-1].lower()/meter, -std::numeric_limits<double>::infinity());
BOOST_TEST_IS_CLOSE(b[0].lower()/meter, 0.0, 1e-9);
BOOST_TEST_IS_CLOSE(b[1].lower()/meter, 1.0, 1e-9);
BOOST_TEST_IS_CLOSE(b[2].lower()/meter, 2.0, 1e-9);
BOOST_TEST_EQ(b[2].upper()/meter, std::numeric_limits<double>::infinity());
BOOST_TEST_EQ(b(-1*meter), -1); // produces NaN in conversion
BOOST_TEST_EQ(b(0*meter), 0);
BOOST_TEST_EQ(b(0.99*meter), 0);
BOOST_TEST_EQ(b(1*meter), 1);
BOOST_TEST_EQ(b(1.99*meter), 1);
BOOST_TEST_EQ(b(2*meter), 2);
BOOST_TEST_EQ(b(100*meter), 2);
BOOST_TEST_EQ(b(std::numeric_limits<double>::infinity()*meter), 2);
}
// axis::circular
{
axis::circular<> a{4, 0, 1};
@@ -248,7 +311,7 @@ int main() {
// std::runtime_error);
}
// axis::any copyable
// axis::variant copyable
{
axis::variant<axis::regular<>> a1(axis::regular<>(2, -1, 1));
axis::variant<axis::regular<>> a2(a1);
@@ -264,11 +327,11 @@ int main() {
a6 = a1;
BOOST_TEST_EQ(a6, a1);
axis::variant<axis::regular<>, axis::integer<>> a7(axis::integer<>(0, 2));
BOOST_TEST_THROWS(axis::variant<axis::regular<>> a8(a7), std::invalid_argument);
BOOST_TEST_THROWS(a4 = a7, std::invalid_argument);
BOOST_TEST_THROWS(axis::variant<axis::regular<>> a8(a7), std::runtime_error);
BOOST_TEST_THROWS(a4 = a7, std::runtime_error);
}
// axis::any movable
// axis::variant movable
{
axis::variant<axis::regular<>> a(axis::regular<>(2, -1, 1));
axis::variant<axis::regular<>> r(a);
@@ -280,51 +343,68 @@ int main() {
BOOST_TEST(c == r);
}
// axis::any streamable
// axis::variant streamable
{
enum { A, B, C };
std::string a = "A";
std::string b = "B";
std::vector<axis::variant<
axis::regular<>,
axis::regular<axis::transform::log<>>,
axis::regular<axis::transform::pow<>>,
axis::circular<>,
axis::variable<>,
axis::category<>,
axis::category<std::string>,
axis::integer<>
>> axes;
axes.push_back(axis::regular<>{2, -1, 1, "regular1"});
axes.push_back(axis::regular<axis::transform::log<>>(2, 1, 10, "regular2",
axis::option_type::none));
axes.push_back(axis::regular<axis::transform::pow<>>(2, 1, 10, "regular3",
axis::option_type::overflow, 0.5));
axes.push_back(axis::regular<axis::transform::pow<>>(2, 1, 10, "regular4",
axis::option_type::none, -0.5));
axes.push_back(axis::circular<>(4, 0.1, 1.0, "polar"));
axes.push_back(axis::variable<>({-1, 0, 1}, "variable", axis::option_type::none));
axes.push_back(axis::category<>({A, B, C}, "category"));
axes.push_back(axis::category<std::string>({a, b}, "category2"));
axes.push_back(axis::integer<>(-1, 1, "integer", axis::option_type::none));
std::ostringstream os;
for (const auto& a : axes) { os << a << "\n"; }
os << axes.back()[0];
const std::string ref =
"regular(2, -1, 1, metadata='regular1', options=underflow_and_overflow)\n"
"regular_log(2, 1, 10, metadata='regular2', options=none)\n"
"regular_pow(2, 1, 10, metadata='regular3', options=overflow, power=0.5)\n"
"regular_pow(2, 1, 10, metadata='regular4', options=none, power=-0.5)\n"
"circular(4, 0.1, 1.1, metadata='polar', options=overflow)\n"
"variable(-1, 0, 1, metadata='variable', options=none)\n"
"category(0, 1, 2, metadata='category', options=overflow)\n"
"category('A', 'B', metadata='category2', options=overflow)\n"
"integer(-1, 1, metadata='integer', options=none)\n"
"[-1, 0)";
BOOST_TEST_EQ(os.str(), ref);
auto test = [](auto&& a, const char* ref) {
using T = detail::rm_cvref<decltype(a)>;
axis::variant<T> axis(std::move(a));
std::ostringstream os;
os << axis;
BOOST_TEST_EQ(os.str(), ref);
};
test(axis::regular<>{2, -1, 1, "regular1"},
"regular(2, -1, 1, metadata='regular1', options=underflow_and_overflow)");
test(axis::regular<axis::transform::log<>>(2, 1, 10, "regular2", axis::option_type::none),
"regular_log(2, 1, 10, metadata='regular2', options=none)");
test(axis::regular<axis::transform::pow<>>(2, 1, 10, "regular3", axis::option_type::overflow, 0.5),
"regular_pow(2, 1, 10, metadata='regular3', options=overflow, power=0.5)");
test(axis::regular<axis::transform::pow<>>(2, 1, 10, "regular4", axis::option_type::none, -0.5),
"regular_pow(2, 1, 10, metadata='regular4', options=none, power=-0.5)");
test(axis::circular<>(4, 0.1, 1.0, "polar"),
"circular(4, 0.1, 1.1, metadata='polar', options=overflow)");
test(axis::variable<>({-1, 0, 1}, "variable", axis::option_type::none),
"variable(-1, 0, 1, metadata='variable', options=none)");
test(axis::category<>({0, 1, 2}, "category"),
"category(0, 1, 2, metadata='category', options=overflow)");
test(axis::category<std::string>({"A", "B"}, "category2"),
"category('A', 'B', metadata='category2', options=overflow)");
test(axis::integer<>(-1, 1, "integer", axis::option_type::none),
"integer(-1, 1, metadata='integer', options=none)");
}
// axis::any equal_comparable
// axis::variant support for minimal_axis
{
struct minimal_axis {
int operator()(double) const { return 0; }
unsigned size() const { return 1; }
};
axis::variant<minimal_axis> axis;
BOOST_TEST_EQ(axis(0), 0);
BOOST_TEST_EQ(axis(10), 0);
BOOST_TEST_EQ(axis.size(), 1);
BOOST_TEST_THROWS(std::ostringstream() << axis, std::runtime_error);
BOOST_TEST_THROWS(axis.lower(0), std::runtime_error);
BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(axis.metadata()), axis::missing_metadata_type&>));
}
// bin_type streamable
{
auto test = [](const auto& x, const char* ref) {
std::ostringstream os;
os << x;
BOOST_TEST_EQ(os.str(), ref);
};
auto a = axis::regular<>(2, 0, 1);
test(a[0], "[0, 0.5)");
auto b = axis::category<>({1, 2});
test(b[0], "1");
}
// axis::variant equal_comparable
{
enum { A, B, C };
using variant = axis::variant<
@@ -351,12 +431,11 @@ int main() {
BOOST_TEST(axes == std::vector<variant>(axes));
}
// axis::any value_to_index_failure
// axis::variant value_to_index_failure
{
std::string a = "A", b = "B";
axis::variant<axis::category<std::string>> x = axis::category<std::string>({a, b}, "category");
axis::variant<axis::category<std::string>> x = axis::category<std::string>({"A", "B"}, "category");
auto cx = axis::get<axis::category<std::string>>(x);
BOOST_TEST_EQ(cx(b), 1);
// BOOST_TEST_EQ(cx(b), 1);
}
// sequence equality
@@ -484,13 +563,13 @@ int main() {
axes.emplace_back(T4(0, 4));
axes.emplace_back(T5({1, 2, 3, 4, 5}, {}, axis::option_type::overflow, a));
}
// 5 axis::any objects
// 5 axis::variant objects
BOOST_TEST_EQ(db[typeid(axis_type)].first, db[typeid(axis_type)].second);
BOOST_TEST_EQ(db[typeid(axis_type)].first, 5);
// 5 labels
// label
BOOST_TEST_EQ(db[typeid(char)].first, db[typeid(char)].second);
BOOST_TEST_GE(db[typeid(char)].first, 3u);
BOOST_TEST_EQ(db[typeid(char)].first, 3u);
// nothing to allocate for T1
// nothing to allocate for T2

View File

@@ -9,6 +9,7 @@
using namespace boost::histogram;
int main() {
auto a = make_dynamic_histogram(axis::integer<>(0, 2));
std::vector<axis::variant<axis::integer<>>> v(1, axis::integer<>(0, 2));
auto a = make_histogram(v);
a(std::make_tuple(1)); // fails, because tuple is intentionally not unpacked
}

View File

@@ -9,6 +9,7 @@
using namespace boost::histogram;
int main() {
auto a = make_dynamic_histogram(axis::integer<>(0, 2));
std::vector<axis::variant<axis::integer<>>> v(1, axis::integer<>(0, 2));
auto a = make_histogram(v);
a(std::vector<int>(1)); // fails, because tuple is intentionally not unpacked
}

View File

@@ -8,7 +8,7 @@
using namespace boost::histogram;
int main() {
auto a = make_static_histogram(axis::integer<>(0, 2));
auto b = make_static_histogram(axis::integer<>(0, 3));
auto a = make_histogram(axis::integer<>(0, 2));
auto b = make_histogram(axis::integer<>(0, 3));
a += b;
}

View File

@@ -11,6 +11,7 @@
#include <boost/histogram/storage/adaptive_storage.hpp>
#include <boost/histogram/storage/array_storage.hpp>
#include <boost/histogram/storage/weight_counter.hpp>
#include <boost/histogram/axis/variant.hpp>
#include <sstream>
#include <stdexcept>
#include <tuple>
@@ -38,23 +39,23 @@ void run_tests() {
// init_1
{
auto h = make(Tag(), axis::regular<>{3, -1, 1});
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.rank(), 1);
BOOST_TEST_EQ(h.size(), 5);
BOOST_TEST_EQ(h.axis(0_c).shape(), 5);
BOOST_TEST_EQ(h.axis().shape(), 5);
BOOST_TEST_EQ(h.axis(0_c).size(), 3);
BOOST_TEST_EQ(h.axis().size(), 3);
auto h2 = make_s(Tag(), array_storage<unsigned>(), axis::regular<>{3, -1, 1});
BOOST_TEST_EQ(h2, h);
}
// init_2
{
auto h = make(Tag(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2});
BOOST_TEST_EQ(h.dim(), 2);
BOOST_TEST_EQ(h.size(), 25);
BOOST_TEST_EQ(h.axis(0_c).shape(), 5);
BOOST_TEST_EQ(h.axis(1_c).shape(), 5);
auto h = make(Tag(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 3});
BOOST_TEST_EQ(h.rank(), 2);
BOOST_TEST_EQ(h.size(), 30);
BOOST_TEST_EQ(h.axis(0_c).size(), 3);
BOOST_TEST_EQ(h.axis(1_c).size(), 4);
auto h2 = make_s(Tag(), array_storage<unsigned>(), axis::regular<>{3, -1, 1},
axis::integer<>{-1, 2});
axis::integer<>{-1, 3});
BOOST_TEST_EQ(h2, h);
}
@@ -62,7 +63,7 @@ void run_tests() {
{
auto h = make(Tag(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2},
axis::circular<>{3});
BOOST_TEST_EQ(h.dim(), 3);
BOOST_TEST_EQ(h.rank(), 3);
BOOST_TEST_EQ(h.size(), 75);
auto h2 = make_s(Tag(), array_storage<unsigned>(), axis::regular<>{3, -1, 1},
axis::integer<>{-1, 2}, axis::circular<>{3});
@@ -73,7 +74,7 @@ void run_tests() {
{
auto h = make(Tag(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2},
axis::circular<>{3}, axis::variable<>{-1, 0, 1});
BOOST_TEST_EQ(h.dim(), 4);
BOOST_TEST_EQ(h.rank(), 4);
BOOST_TEST_EQ(h.size(), 300);
auto h2 =
make_s(Tag(), array_storage<unsigned>(), axis::regular<>{3, -1, 1},
@@ -87,7 +88,7 @@ void run_tests() {
auto h = make(Tag(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2},
axis::circular<>{3}, axis::variable<>{-1, 0, 1},
axis::category<>{{A, B, C}});
BOOST_TEST_EQ(h.dim(), 5);
BOOST_TEST_EQ(h.rank(), 5);
BOOST_TEST_EQ(h.size(), 1200);
auto h2 = make_s(Tag(), array_storage<unsigned>(), axis::regular<>{3, -1, 1},
axis::integer<>{-1, 2}, axis::circular<>{3},
@@ -131,51 +132,49 @@ void run_tests() {
const auto href = h;
decltype(h) h2(std::move(h));
// static axes cannot shrink to zero
BOOST_TEST_EQ(h.dim(), expected_moved_from_dim(Tag(), 2));
BOOST_TEST_EQ(sum(h).value(), 0);
BOOST_TEST_EQ(h.rank(), expected_moved_from_dim(Tag(), 2));
BOOST_TEST_EQ(sum(h), 0);
BOOST_TEST_EQ(h.size(), 0);
BOOST_TEST_EQ(h2, href);
decltype(h) h3;
h3 = std::move(h2);
// static axes cannot shrink to zero
BOOST_TEST_EQ(h2.dim(), expected_moved_from_dim(Tag(), 2));
BOOST_TEST_EQ(sum(h2).value(), 0);
BOOST_TEST_EQ(h2.rank(), expected_moved_from_dim(Tag(), 2));
BOOST_TEST_EQ(sum(h2), 0);
BOOST_TEST_EQ(h2.size(), 0);
BOOST_TEST_EQ(h3, href);
}
// axis methods
{
enum { A = 3, B = 5 };
auto a = make(Tag(), axis::regular<>(1, 1, 2, "foo"));
BOOST_TEST_EQ(a.axis().size(), 1);
BOOST_TEST_EQ(a.axis().shape(), 3);
BOOST_TEST_EQ(a.axis().index(1), 0);
BOOST_TEST_EQ(a.axis()[0].lower(), 1);
BOOST_TEST_EQ(a.axis()[0].upper(), 2);
BOOST_TEST_EQ(a.axis().label(), "foo");
a.axis().label("bar");
BOOST_TEST_EQ(a.axis().label(), "bar");
BOOST_TEST_EQ(a.axis().metadata(), "foo");
a.axis().metadata() = "bar";
BOOST_TEST_EQ(a.axis().metadata(), "bar");
auto b = make(Tag(), axis::integer<>(1, 2));
BOOST_TEST_EQ(b.axis().size(), 1);
BOOST_TEST_EQ(b.axis().shape(), 3);
BOOST_TEST_EQ(b.axis().index(1), 0);
BOOST_TEST_EQ(b.axis()[0].lower(), 1);
BOOST_TEST_EQ(b.axis()[0].upper(), 2);
b.axis().label("foo");
BOOST_TEST_EQ(b.axis().label(), "foo");
auto b = make(Tag(), axis::regular<>(1, 1, 2, "foo"),
axis::integer<>(1, 3));
BOOST_TEST_EQ(b.axis(0_c).size(), 1);
BOOST_TEST_EQ(b.axis(0_c)[0].lower(), 1);
BOOST_TEST_EQ(b.axis(0_c)[0].upper(), 2);
BOOST_TEST_EQ(b.axis(1_c).size(), 2);
BOOST_TEST_EQ(b.axis(1_c)[0].lower(), 1);
BOOST_TEST_EQ(b.axis(1_c)[0].upper(), 3);
b.axis(1_c).metadata() = "bar";
BOOST_TEST_EQ(b.axis(0_c).metadata(), "foo");
BOOST_TEST_EQ(b.axis(1_c).metadata(), "bar");
auto c = make(Tag(), axis::category<>({A, B}));
enum class C { A = 3, B = 5 };
auto c = make(Tag(), axis::category<C>({C::A, C::B}));
BOOST_TEST_EQ(c.axis().size(), 2);
BOOST_TEST_EQ(c.axis().shape(), 3);
BOOST_TEST_EQ(c.axis().index(A), 0);
BOOST_TEST_EQ(c.axis().index(B), 1);
c.axis().label("foo");
BOOST_TEST_EQ(c.axis().label(), "foo");
c.axis().metadata() = "foo";
BOOST_TEST_EQ(c.axis().metadata(), "foo");
// need to cast here for this to work with Tag == dynamic_tag, too
auto ca = static_cast<const axis::category<>&>(c.axis());
BOOST_TEST_EQ(ca[0].value(), A);
auto ca = axis::get<axis::category<C>>(c.axis());
BOOST_TEST(ca[0].value() == C::A);
}
// equal_compare
@@ -211,9 +210,8 @@ void run_tests() {
h(-1);
h(10);
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.axis(0_c).size(), 2);
BOOST_TEST_EQ(h.axis(0_c).shape(), 4);
BOOST_TEST_EQ(h.rank(), 1);
BOOST_TEST_EQ(h.axis().size(), 2);
BOOST_TEST_EQ(sum(h), 4);
BOOST_TEST_EQ(h.at(-1), 1);
@@ -224,15 +222,14 @@ void run_tests() {
// d1_2
{
auto h = make(Tag(), axis::integer<>(0, 2, "", axis::uoflow_type::off));
auto h = make(Tag(), axis::integer<>(0, 2, "", axis::option_type::none));
h(0);
h(-0);
h(-1);
h(10);
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.axis(0_c).size(), 2);
BOOST_TEST_EQ(h.axis(0_c).shape(), 2);
BOOST_TEST_EQ(h.rank(), 1);
BOOST_TEST_EQ(h.axis().size(), 2);
BOOST_TEST_EQ(sum(h), 2);
BOOST_TEST_EQ(h.at(0), 2);
@@ -247,18 +244,19 @@ void run_tests() {
h("D");
h("E");
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.axis(0_c).size(), 2);
BOOST_TEST_EQ(h.axis(0_c).shape(), 3);
BOOST_TEST_EQ(h.rank(), 1);
BOOST_TEST_EQ(h.axis().size(), 2);
BOOST_TEST_EQ(sum(h), 4);
BOOST_TEST_EQ(h.at(0), 1);
BOOST_TEST_EQ(h.at(1), 1);
BOOST_TEST_EQ(h.at(2), 2); // overflow bin
}
// d1w
{
auto h = make(Tag(), axis::integer<>(0, 2));
auto h = make_s(Tag(), array_storage<weight_counter<>>(),
axis::integer<>(0, 2));
h(-1);
h(0);
h(weight(0.5), 0);
@@ -282,17 +280,15 @@ void run_tests() {
// d2
{
auto h = make(Tag(), axis::regular<>(2, -1, 1),
axis::integer<>(-1, 2, "", axis::uoflow_type::off));
axis::integer<>(-1, 2, {}, axis::option_type::none));
h(-1, -1);
h(-1, 0);
h(-1, -10);
h(-10, 0);
BOOST_TEST_EQ(h.dim(), 2);
BOOST_TEST_EQ(h.rank(), 2);
BOOST_TEST_EQ(h.axis(0_c).size(), 2);
BOOST_TEST_EQ(h.axis(0_c).shape(), 4);
BOOST_TEST_EQ(h.axis(1_c).size(), 3);
BOOST_TEST_EQ(h.axis(1_c).shape(), 3);
BOOST_TEST_EQ(sum(h), 3);
BOOST_TEST_EQ(h.at(-1, 0), 0);
@@ -314,8 +310,10 @@ void run_tests() {
// d2w
{
auto h = make(Tag(), axis::regular<>(2, -1, 1),
axis::integer<>(-1, 2, "", axis::uoflow_type::off));
auto h = make_s(Tag(),
array_storage<weight_counter<>>(),
axis::regular<>(2, -1, 1),
axis::integer<>(-1, 2, {}, axis::option_type::none));
h(-1, 0); // -> 0, 1
h(weight(10), -1, -1); // -> 0, 0
h(weight(5), -1, -10); // is ignored
@@ -359,17 +357,20 @@ void run_tests() {
// d3w
{
auto h =
make(Tag(), axis::integer<>(0, 3), axis::integer<>(0, 4), axis::integer<>(0, 5));
for (auto i = 0; i < h.axis(0_c).size(); ++i) {
for (auto j = 0; j < h.axis(1_c).size(); ++j) {
for (auto k = 0; k < h.axis(2_c).size(); ++k) { h(weight(i + j + k), i, j, k); }
auto h = make_s(Tag(),
array_storage<weight_counter<>>(),
axis::integer<>(0, 3),
axis::integer<>(0, 4),
axis::integer<>(0, 5));
for (auto i = 0u; i < h.axis(0_c).size(); ++i) {
for (auto j = 0u; j < h.axis(1_c).size(); ++j) {
for (auto k = 0u; k < h.axis(2_c).size(); ++k) { h(weight(i + j + k), i, j, k); }
}
}
for (auto i = 0; i < h.axis(0_c).size(); ++i) {
for (auto j = 0; j < h.axis(1_c).size(); ++j) {
for (auto k = 0; k < h.axis(2_c).size(); ++k) {
for (auto i = 0u; i < h.axis(0_c).size(); ++i) {
for (auto j = 0u; j < h.axis(1_c).size(); ++j) {
for (auto k = 0u; k < h.axis(2_c).size(); ++k) {
BOOST_TEST_EQ(h.at(i, j, k).value(), i + j + k);
BOOST_TEST_EQ(h.at(i, j, k).variance(), (i + j + k) * (i + j + k));
}
@@ -402,8 +403,10 @@ void run_tests() {
// add_2
{
auto a = make(Tag(), axis::integer<>(0, 2));
auto b = make(Tag(), axis::integer<>(0, 2));
auto a = make_s(Tag(), array_storage<weight_counter<>>(),
axis::integer<>(0, 2));
auto b = make_s(Tag(), array_storage<weight_counter<>>(),
axis::integer<>(0, 2));
a(0);
BOOST_TEST_EQ(a.at(0).variance(), 1);
@@ -476,20 +479,20 @@ void run_tests() {
BOOST_TEST_EQ(d.at(1), 3);
auto e = 3 * a;
auto f = b * 2;
BOOST_TEST_EQ(e.at(0).value(), 3);
BOOST_TEST_EQ(e.at(1).value(), 0);
BOOST_TEST_EQ(f.at(0).value(), 0);
BOOST_TEST_EQ(f.at(1).value(), 2);
BOOST_TEST_EQ(e.at(0), 3);
BOOST_TEST_EQ(e.at(1), 0);
BOOST_TEST_EQ(f.at(0), 0);
BOOST_TEST_EQ(f.at(1), 2);
auto r = a;
r += b;
r += e;
BOOST_TEST_EQ(r.at(0).value(), 4);
BOOST_TEST_EQ(r.at(1).value(), 1);
BOOST_TEST_EQ(r.at(0), 4);
BOOST_TEST_EQ(r.at(1), 1);
BOOST_TEST_EQ(r, a + b + 3 * a);
auto s = r / 4;
r /= 4;
BOOST_TEST_EQ(r.at(0).value(), 1);
BOOST_TEST_EQ(r.at(1).value(), 0.25);
BOOST_TEST_EQ(r.at(0), 1);
BOOST_TEST_EQ(r.at(1), 0.25);
BOOST_TEST_EQ(r, s);
}
@@ -500,14 +503,14 @@ void run_tests() {
os << a;
BOOST_TEST_EQ(os.str(),
"histogram("
"\n regular(3, -1, 1, label='r'),"
"\n integer(0, 2, label='i'),"
"\n regular(3, -1, 1, metadata='r', options=underflow_and_overflow),"
"\n integer(0, 2, metadata='i', options=underflow_and_overflow),"
"\n)");
}
// histogram_reset
{
auto h = make(Tag(), axis::integer<>(0, 2, "", axis::uoflow_type::off));
auto h = make(Tag(), axis::integer<>(0, 2, {}, axis::option_type::none));
h(0);
h(1);
BOOST_TEST_EQ(h.at(0), 1);
@@ -540,16 +543,14 @@ void run_tests() {
*/
auto h1_0 = h1.reduce_to(0_c);
BOOST_TEST_EQ(h1_0.dim(), 1);
BOOST_TEST_EQ(h1_0.rank(), 1);
BOOST_TEST_EQ(sum(h1_0), 5);
BOOST_TEST_EQ(h1_0.at(0), 2);
BOOST_TEST_EQ(h1_0.at(1), 3);
BOOST_TEST_EQ(h1_0.axis()[0].lower(), 0);
BOOST_TEST_EQ(h1_0.axis()[1].lower(), 1);
BOOST_TEST(h1_0.axis() == h1.axis(0_c));
auto h1_1 = h1.reduce_to(1_c);
BOOST_TEST_EQ(h1_1.dim(), 1);
BOOST_TEST_EQ(h1_1.rank(), 1);
BOOST_TEST_EQ(sum(h1_1), 5);
BOOST_TEST_EQ(h1_1.at(0), 2);
BOOST_TEST_EQ(h1_1.at(1), 2);
@@ -565,21 +566,21 @@ void run_tests() {
h2(1, 0, 2);
auto h2_0 = h2.reduce_to(0_c);
BOOST_TEST_EQ(h2_0.dim(), 1);
BOOST_TEST_EQ(h2_0.rank(), 1);
BOOST_TEST_EQ(sum(h2_0), 5);
BOOST_TEST_EQ(h2_0.at(0), 4);
BOOST_TEST_EQ(h2_0.at(1), 1);
BOOST_TEST(h2_0.axis() == axis::integer<>(0, 2));
auto h2_1 = h2.reduce_to(1_c);
BOOST_TEST_EQ(h2_1.dim(), 1);
BOOST_TEST_EQ(h2_1.rank(), 1);
BOOST_TEST_EQ(sum(h2_1), 5);
BOOST_TEST_EQ(h2_1.at(0), 3);
BOOST_TEST_EQ(h2_1.at(1), 2);
BOOST_TEST(h2_1.axis() == axis::integer<>(0, 3));
auto h2_2 = h2.reduce_to(2_c);
BOOST_TEST_EQ(h2_2.dim(), 1);
BOOST_TEST_EQ(h2_2.rank(), 1);
BOOST_TEST_EQ(sum(h2_2), 5);
BOOST_TEST_EQ(h2_2.at(0), 2);
BOOST_TEST_EQ(h2_2.at(1), 1);
@@ -587,7 +588,7 @@ void run_tests() {
BOOST_TEST(h2_2.axis() == axis::integer<>(0, 4));
auto h2_01 = h2.reduce_to(0_c, 1_c);
BOOST_TEST_EQ(h2_01.dim(), 2);
BOOST_TEST_EQ(h2_01.rank(), 2);
BOOST_TEST_EQ(sum(h2_01), 5);
BOOST_TEST_EQ(h2_01.at(0, 0), 2);
BOOST_TEST_EQ(h2_01.at(0, 1), 2);
@@ -596,7 +597,7 @@ void run_tests() {
BOOST_TEST(h2_01.axis(1_c) == axis::integer<>(0, 3));
auto h2_02 = h2.reduce_to(0_c, 2_c);
BOOST_TEST_EQ(h2_02.dim(), 2);
BOOST_TEST_EQ(h2_02.rank(), 2);
BOOST_TEST_EQ(sum(h2_02), 5);
BOOST_TEST_EQ(h2_02.at(0, 0), 2);
BOOST_TEST_EQ(h2_02.at(0, 1), 1);
@@ -606,7 +607,7 @@ void run_tests() {
BOOST_TEST(h2_02.axis(1_c) == axis::integer<>(0, 4));
auto h2_12 = h2.reduce_to(1_c, 2_c);
BOOST_TEST_EQ(h2_12.dim(), 2);
BOOST_TEST_EQ(h2_12.rank(), 2);
BOOST_TEST_EQ(sum(h2_12), 5);
BOOST_TEST_EQ(h2_12.at(0, 0), 1);
BOOST_TEST_EQ(h2_12.at(1, 0), 1);
@@ -619,14 +620,12 @@ void run_tests() {
// custom axis
{
struct custom_axis : public axis::integer<> {
using value_type = const char*; // type that is fed to the axis
using integer::integer; // inherit ctors of base
// the customization point
// - accept const char* and convert to int
// - then call index method of base class
int index(value_type s) const { return integer::index(std::atoi(s)); }
// customization point: convert argument and call base class
int operator()(const char* s) const {
return integer::operator()(std::atoi(s));
}
};
auto h = make(Tag(), custom_axis(0, 3));
@@ -635,7 +634,7 @@ void run_tests() {
h("1");
h("9");
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.rank(), 1);
BOOST_TEST_EQ(h.axis(), custom_axis(0, 3));
BOOST_TEST_EQ(h.at(0), 1);
BOOST_TEST_EQ(h.at(1), 1);
@@ -644,13 +643,14 @@ void run_tests() {
// histogram iterator 1D
{
auto h = make(Tag(), axis::integer<>(0, 3));
auto h = make_s(Tag(), array_storage<weight_counter<>>(),
axis::integer<>(0, 3));
const auto& a = h.axis();
h(weight(2), 0);
h(1);
h(1);
auto it = h.begin();
BOOST_TEST_EQ(it.dim(), 1);
BOOST_TEST_EQ(it.rank(), 1);
BOOST_TEST_EQ(it.idx(), 0);
BOOST_TEST_EQ(it.bin(), a[0]);
@@ -678,8 +678,10 @@ void run_tests() {
// histogram iterator 2D
{
auto h = make(Tag(), axis::integer<>(0, 1),
axis::integer<>(2, 4, "", axis::uoflow_type::off));
auto h = make_s(Tag(),
array_storage<weight_counter<>>(),
axis::integer<>(0, 1),
axis::integer<>(2, 4, "", axis::option_type::none));
const auto& a0 = h.axis(0_c);
const auto& a1 = h.axis(1_c);
h(weight(2), 0, 2);
@@ -687,7 +689,7 @@ void run_tests() {
h(1, 3);
auto it = h.begin();
BOOST_TEST_EQ(it.dim(), 2);
BOOST_TEST_EQ(it.rank(), 2);
BOOST_TEST_EQ(it.idx(0), 0);
BOOST_TEST_EQ(it.idx(1), 0);
@@ -742,16 +744,18 @@ void run_tests() {
{
auto h = make(Tag(), axis::integer<>(0, 3));
for (int i = 0; i < 3; ++i) h(i);
auto a = std::vector<weight_counter<double>>();
auto a = std::vector<double>();
std::partial_sum(h.begin(), h.end(), std::back_inserter(a));
BOOST_TEST_EQ(a[0].value(), 1);
BOOST_TEST_EQ(a[1].value(), 2);
BOOST_TEST_EQ(a[2].value(), 3);
BOOST_TEST_EQ(a[0], 1);
BOOST_TEST_EQ(a[1], 2);
BOOST_TEST_EQ(a[2], 3);
}
// using STL containers
{
auto h = make(Tag(), axis::integer<>(0, 2), axis::regular<>(2, 2, 4));
auto h = make_s(Tag(),
array_storage<weight_counter<>>(),
axis::integer<>(0, 2), axis::regular<>(2, 2, 4));
// vector in
h(std::vector<int>({0, 2}));
// pair in
@@ -805,9 +809,8 @@ void run_tests() {
tracing_allocator_db db;
{
tracing_allocator<char> a(db);
auto h = make_s(Tag(), array_storage<int, int, tracing_allocator<int>>(a),
axis::integer<int, tracing_allocator<char>>(
0, 1024, std::string(512, 'c'), axis::uoflow_type::on, a));
auto h = make_s(Tag(), array_storage<int, tracing_allocator<int>>(a),
axis::integer<>(0, 1024));
h(0);
}
@@ -815,12 +818,8 @@ void run_tests() {
BOOST_TEST_EQ(db[typeid(int)].first, db[typeid(int)].second);
BOOST_TEST_GE(db[typeid(int)].first, 1024u);
// char allocation for axis label
BOOST_TEST_EQ(db[typeid(char)].first, db[typeid(char)].second);
BOOST_TEST_GE(db[typeid(char)].first, 512u);
if (Tag()) { // axis::any allocation, only for dynamic histogram
using T = axis::any<axis::integer<int, tracing_allocator<char>>>;
if (Tag()) { // axis::variant allocation, only for dynamic histogram
using T = axis::variant<axis::integer<>>;
BOOST_TEST_EQ(db[typeid(T)].first, db[typeid(T)].second);
BOOST_TEST_GE(db[typeid(T)].first, 1u);
}

View File

@@ -126,6 +126,14 @@ int main() {
BOOST_TEST_TRAIT_TRUE((is_iterable<C>));
}
// is_streamable
{
struct Foo {};
BOOST_TEST_TRAIT_TRUE((is_streamable<int>));
BOOST_TEST_TRAIT_TRUE((is_streamable<std::string>));
BOOST_TEST_TRAIT_FALSE((is_streamable<Foo>));
}
// is_axis_variant
{
struct A {};
@@ -136,29 +144,36 @@ int main() {
// classify_container
{
using result1 = classify_container<int>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result1, no_container_tag>));
using A = classify_container<int>;
BOOST_TEST_TRAIT_TRUE((std::is_same<A, no_container_tag>));
using result1a = classify_container<int&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result1a, no_container_tag>));
using B = classify_container<int&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<B, no_container_tag>));
using result2 = classify_container<std::vector<int>>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result2, dynamic_container_tag>));
using C = classify_container<std::vector<int>>;
BOOST_TEST_TRAIT_TRUE((std::is_same<C, iterable_container_tag>));
using result2a = classify_container<std::vector<int>&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result2a, dynamic_container_tag>));
using D = classify_container<std::vector<int>&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<D, iterable_container_tag>));
using result3 = classify_container<std::pair<int, int>>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result3, static_container_tag>));
using E = classify_container<std::pair<int, int>>;
BOOST_TEST_TRAIT_TRUE((std::is_same<E, static_container_tag>));
using result3a = classify_container<std::pair<int, int>&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result3a, static_container_tag>));
using F = classify_container<std::pair<int, int>&>;
BOOST_TEST_TRAIT_TRUE((std::is_same<F, static_container_tag>));
using result4 = classify_container<std::string>;
BOOST_TEST_TRAIT_TRUE((std::is_same<result4, dynamic_container_tag>));
using G = classify_container<std::string>;
BOOST_TEST_TRAIT_TRUE((std::is_same<G, iterable_container_tag>));
using result5 = classify_container<int*>; // has no std::end
BOOST_TEST_TRAIT_TRUE((std::is_same<result5, no_container_tag>));
using H = classify_container<int*>; // has no std::end
BOOST_TEST_TRAIT_TRUE((std::is_same<H, no_container_tag>));
using I = classify_container<std::initializer_list<int>>;
BOOST_TEST_TRAIT_TRUE((std::is_same<I, iterable_container_tag>));
auto j = {0, 1};
using J = classify_container<decltype(j)>;
BOOST_TEST_TRAIT_TRUE((std::is_same<I, iterable_container_tag>));
}
// bool mask
@@ -244,6 +259,17 @@ int main() {
BOOST_TEST_TRAIT_TRUE((std::is_same<unqualified_iterator_value_type<T2>, int>));
}
// args_type
{
struct Foo {
static int f1(char);
int f2(long) const;
};
BOOST_TEST_TRAIT_TRUE((std::is_same<args_type<decltype(&Foo::f1)>, std::tuple<char>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<args_type<decltype(&Foo::f2)>, std::tuple<long>>));
}
// visitor_return_type
{
using V1 = bh::axis::variant<char>;