fix of reduce when histogram lacks flow bins

reducing histograms with axes that lacked flow bins failed before this patch
This commit is contained in:
Hans Dembinski 2019-12-15 18:04:20 +01:00 committed by GitHub
parent 1540c4e94a
commit 81cf62d010
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 8 deletions

View File

@ -263,26 +263,44 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
++iaxis;
});
auto storage = detail::make_default(unsafe_access::storage(hist));
auto result = Histogram(std::move(axes), std::move(storage));
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
auto idx = detail::make_stack_buffer<int>(axes);
auto irange = detail::make_stack_buffer<std::pair<int, int>>(axes);
detail::for_each_axis(axes, [it = irange.begin()](const auto& a) mutable {
using A = std::decay_t<decltype(a)>;
it->first = axis::traits::static_options<A>::test(axis::option::underflow) ? -1 : 0;
it->second = axis::traits::static_options<A>::test(axis::option::overflow)
? a.size() + 1
: a.size();
++it;
});
auto result =
Histogram(std::move(axes), detail::make_default(unsafe_access::storage(hist)));
for (auto&& x : indexed(hist, coverage::all)) {
auto i = idx.begin();
auto o = opts.begin();
auto ir = irange.begin();
bool valid = true;
for (auto j : x.indices()) {
*i = (j - o->begin);
if (*i <= -1)
if (*i <= -1) {
*i = -1;
else {
if (*i < ir->first) valid = false;
} else {
*i /= o->merge;
const int end = (o->end - o->begin) / o->merge;
if (*i > end) *i = end;
if (*i >= end) {
*i = end;
if (*i >= ir->second) valid = false;
}
}
++i;
++o;
++ir;
}
result.at(idx) += *x;
if (valid) result.at(idx) += *x;
}
return result;

View File

@ -224,6 +224,43 @@ void run_tests() {
BOOST_TEST_EQ(reduce(h, shrink(2, -1.001)).axis(), R(4, 2, -2));
BOOST_TEST_EQ(reduce(h, shrink(2, -1)).axis(), R(3, 2, -1));
}
// reduce on histogram with axis without flow bins, see GitHub issue #257
{
auto h = make(Tag(), axis::integer<int, use_default, axis::option::underflow_t>(0, 3),
axis::integer<int, use_default, axis::option::overflow_t>(0, 3));
std::fill(h.begin(), h.end(), 1);
/*
Original histogram:
x
-1 0 1 2
-------------
0| 1 1 1 1
x 1| 1 1 1 1
2| 1 1 1 1
3| 1 1 1 1
Shrunk histogram:
-1 0
-------
0| 2 1
1| 4 2
*/
auto hr = reduce(h, slice(0, 1, 2), slice(1, 1, 2));
BOOST_TEST_EQ(hr.size(), 2 * 2);
BOOST_TEST_EQ(hr.axis(0).size(), 1);
BOOST_TEST_EQ(hr.axis(1).size(), 1);
BOOST_TEST_EQ(hr.axis(0).bin(0), 1);
BOOST_TEST_EQ(hr.axis(1).bin(0), 1);
BOOST_TEST_EQ(hr.at(-1, 0), 2);
BOOST_TEST_EQ(hr.at(0, 0), 1);
BOOST_TEST_EQ(hr.at(-1, 1), 4);
BOOST_TEST_EQ(hr.at(0, 1), 2);
}
}
int main() {