use integral constants to access axis in histogram statically

This commit is contained in:
Hans Dembinski
2017-04-25 10:10:22 +02:00
parent 00807ca54d
commit a2bc4f428d
5 changed files with 99 additions and 45 deletions

View File

@@ -213,12 +213,6 @@ public:
return axes_[i];
}
/// Return axis \a i (for conformity with histogram<Static, ...> interface)
template <unsigned N = 0> const axis_type &axis() const {
BOOST_ASSERT_MSG(N < dim(), "axis index out of range");
return axes_[N];
}
/// Apply unary functor/function to each axis
template <typename Unary> void for_each_axis(Unary &unary) const {
for (const auto &a : axes_) {

View File

@@ -150,14 +150,24 @@ public:
/// Reset bin counters to zero
void reset() { storage_ = std::move(Storage(storage_.size())); }
template <unsigned N = 0>
/// Get N-th axis
template <unsigned N>
constexpr
typename std::add_const<
typename fusion::result_of::value_at_c<axes_type, N>::type>::type &
axis() const {
axis(std::integral_constant<unsigned, N>) const {
static_assert(N < axes_size::value, "axis index out of range");
return fusion::at_c<N>(axes_);
}
// Get first axis (convenience for 1-d histograms)
constexpr
typename std::add_const<
typename fusion::result_of::value_at_c<axes_type, 0>::type>::type &
axis() const {
return fusion::at_c<0>(axes_);
}
/// Apply unary functor/function to each axis
template <typename Unary> void for_each_axis(Unary &unary) const {
fusion::for_each(axes_, unary);

View File

@@ -0,0 +1,45 @@
// 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)
#ifndef _BOOST_HISTOGRAM_LITERALS_HPP_
#define _BOOST_HISTOGRAM_LITERALS_HPP_
#include <type_traits>
namespace boost {
namespace histogram {
namespace literals {
namespace detail {
template <char C> struct char2int;
template <> struct char2int<'0'> { static constexpr unsigned value = 0; };
template <> struct char2int<'1'> { static constexpr unsigned value = 1; };
template <> struct char2int<'2'> { static constexpr unsigned value = 2; };
template <> struct char2int<'3'> { static constexpr unsigned value = 3; };
template <> struct char2int<'4'> { static constexpr unsigned value = 4; };
template <> struct char2int<'5'> { static constexpr unsigned value = 5; };
template <> struct char2int<'6'> { static constexpr unsigned value = 6; };
template <> struct char2int<'7'> { static constexpr unsigned value = 7; };
template <> struct char2int<'8'> { static constexpr unsigned value = 8; };
template <> struct char2int<'9'> { static constexpr unsigned value = 9; };
template <unsigned N>
constexpr unsigned parse() { return N; }
template <unsigned N, char First, char... Rest>
constexpr unsigned parse() { return parse<N * 10 + char2int<First>::value, Rest...>(); }
} // NS detail
template <char... Digits>
auto operator"" _c() -> decltype(std::integral_constant<unsigned, detail::parse<0, Digits...>()>())
{
return std::integral_constant<unsigned, detail::parse<0, Digits...>()>();
}
} // NS literals
} // NS histogram
} // NS boost
#endif

View File

@@ -16,6 +16,7 @@
#include <boost/histogram/storage/adaptive_storage.hpp>
#include <boost/histogram/storage/container_storage.hpp>
#include <boost/histogram/utility.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/mpl/vector.hpp>
#include <limits>
#include <sstream>
@@ -23,6 +24,7 @@
int main() {
using namespace boost::histogram;
using namespace boost::histogram::literals;
namespace mpl = boost::mpl;
// init_0
@@ -40,7 +42,7 @@ int main() {
auto h = histogram<Dynamic, default_axes>(regular_axis<>{3, -1, 1});
BOOST_TEST_EQ(h.dim(), 1u);
BOOST_TEST_EQ(h.size(), 5u);
BOOST_TEST_EQ(shape(h.axis<0>()), 5);
BOOST_TEST_EQ(shape(h.axis(0_c)), 5);
auto h2 = histogram<Dynamic, default_axes,
container_storage<std::vector<unsigned>>>(
regular_axis<>{3, -1, 1});
@@ -53,8 +55,8 @@ int main() {
integer_axis{-1, 1});
BOOST_TEST_EQ(h.dim(), 2u);
BOOST_TEST_EQ(h.size(), 25u);
BOOST_TEST_EQ(shape(h.axis<0>()), 5);
BOOST_TEST_EQ(shape(h.axis<1>()), 5);
BOOST_TEST_EQ(shape(h.axis(0_c)), 5);
BOOST_TEST_EQ(shape(h.axis(1_c)), 5);
auto h2 = histogram<Dynamic, default_axes,
container_storage<std::vector<unsigned>>>(
regular_axis<>{3, -1, 1}, integer_axis{-1, 1});
@@ -106,8 +108,8 @@ int main() {
v.push_back(regular_axis<>(100, -1, 1));
v.push_back(integer_axis(1, 6));
auto h = histogram<Dynamic, default_axes>(v.begin(), v.end());
BOOST_TEST_EQ(h.axis<0>(), v[0]);
BOOST_TEST_EQ(h.axis<1>(), v[1]);
BOOST_TEST_EQ(h.axis(0_c), v[0]);
BOOST_TEST_EQ(h.axis(1_c), v[1]);
BOOST_TEST_EQ(h.axis(0), v[0]);
BOOST_TEST_EQ(h.axis(1), v[1]);
}
@@ -196,8 +198,8 @@ int main() {
h.fill(10);
BOOST_TEST_EQ(h.dim(), 1u);
BOOST_TEST_EQ(bins(h.axis<>()), 2);
BOOST_TEST_EQ(shape(h.axis<>()), 4);
BOOST_TEST_EQ(bins(h.axis()), 2);
BOOST_TEST_EQ(shape(h.axis()), 4);
BOOST_TEST_EQ(h.sum(), 4.0);
BOOST_TEST_THROWS(h.value(-2), std::out_of_range);
@@ -224,8 +226,8 @@ int main() {
h.fill(10);
BOOST_TEST_EQ(h.dim(), 1u);
BOOST_TEST_EQ(bins(h.axis<>()), 2);
BOOST_TEST_EQ(shape(h.axis<>()), 2);
BOOST_TEST_EQ(bins(h.axis()), 2);
BOOST_TEST_EQ(shape(h.axis()), 2);
BOOST_TEST_EQ(h.sum(), 2);
BOOST_TEST_THROWS(h.value(-1), std::out_of_range);
@@ -271,10 +273,10 @@ int main() {
h.fill(-10, 0);
BOOST_TEST_EQ(h.dim(), 2u);
BOOST_TEST_EQ(bins(h.axis<0>()), 2);
BOOST_TEST_EQ(shape(h.axis<0>()), 4);
BOOST_TEST_EQ(bins(h.axis<1>()), 3);
BOOST_TEST_EQ(shape(h.axis<1>()), 3);
BOOST_TEST_EQ(bins(h.axis(0_c)), 2);
BOOST_TEST_EQ(shape(h.axis(0_c)), 4);
BOOST_TEST_EQ(bins(h.axis(1_c)), 3);
BOOST_TEST_EQ(shape(h.axis(1_c)), 3);
BOOST_TEST_EQ(h.sum(), 3);
BOOST_TEST_EQ(h.value(-1, 0), 0.0);
@@ -358,17 +360,17 @@ int main() {
{
auto h = make_dynamic_histogram(integer_axis(0, 3), integer_axis(0, 4),
integer_axis(0, 5));
for (auto i = 0; i < bins(h.axis<0>()); ++i) {
for (auto j = 0; j < bins(h.axis<1>()); ++j) {
for (auto k = 0; k < bins(h.axis<2>()); ++k) {
for (auto i = 0; i < bins(h.axis(0_c)); ++i) {
for (auto j = 0; j < bins(h.axis(1_c)); ++j) {
for (auto k = 0; k < bins(h.axis(2_c)); ++k) {
h.wfill(i + j + k, i, j, k);
}
}
}
for (auto i = 0; i < bins(h.axis<0>()); ++i) {
for (auto j = 0; j < bins(h.axis<1>()); ++j) {
for (auto k = 0; k < bins(h.axis<2>()); ++k) {
for (auto i = 0; i < bins(h.axis(0_c)); ++i) {
for (auto j = 0; j < bins(h.axis(1_c)); ++j) {
for (auto k = 0; k < bins(h.axis(2_c)); ++k) {
BOOST_TEST_EQ(h.value(i, j, k), i + j + k);
}
}

View File

@@ -14,12 +14,14 @@
#include <boost/histogram/storage/adaptive_storage.hpp>
#include <boost/histogram/storage/container_storage.hpp>
#include <boost/histogram/utility.hpp>
#include <boost/histogram/literals.hpp>
#include <limits>
#include <sstream>
#include <vector>
int main() {
using namespace boost::histogram;
using namespace boost::histogram::literals;
namespace mpl = boost::mpl;
// init_0
@@ -41,7 +43,8 @@ int main() {
regular_axis<>{3, -1, 1});
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(h.size(), 5);
BOOST_TEST_EQ(shape(h.axis<0>()), 5);
BOOST_TEST_EQ(shape(h.axis(0_c)), 5);
BOOST_TEST_EQ(shape(h.axis()), 5);
auto h2 =
make_static_histogram_with<container_storage<std::vector<unsigned>>>(
regular_axis<>{3, -1, 1});
@@ -54,8 +57,8 @@ int main() {
regular_axis<>{3, -1, 1}, integer_axis{-1, 1});
BOOST_TEST_EQ(h.dim(), 2);
BOOST_TEST_EQ(h.size(), 25);
BOOST_TEST_EQ(shape(h.axis<0>()), 5);
BOOST_TEST_EQ(shape(h.axis<1>()), 5);
BOOST_TEST_EQ(shape(h.axis(0_c)), 5);
BOOST_TEST_EQ(shape(h.axis(1_c)), 5);
auto h2 =
make_static_histogram_with<container_storage<std::vector<unsigned>>>(
regular_axis<>{3, -1, 1}, integer_axis{-1, 1});
@@ -182,8 +185,8 @@ int main() {
h.fill(10);
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(bins(h.axis<0>()), 2);
BOOST_TEST_EQ(shape(h.axis<0>()), 4);
BOOST_TEST_EQ(bins(h.axis(0_c)), 2);
BOOST_TEST_EQ(shape(h.axis(0_c)), 4);
BOOST_TEST_EQ(h.sum(), 4);
BOOST_TEST_THROWS(h.value(-2), std::out_of_range);
@@ -210,8 +213,8 @@ int main() {
h.fill(10);
BOOST_TEST_EQ(h.dim(), 1);
BOOST_TEST_EQ(bins(h.axis<0>()), 2);
BOOST_TEST_EQ(shape(h.axis<0>()), 2);
BOOST_TEST_EQ(bins(h.axis(0_c)), 2);
BOOST_TEST_EQ(shape(h.axis(0_c)), 2);
BOOST_TEST_EQ(h.sum(), 2);
BOOST_TEST_THROWS(h.value(-1), std::out_of_range);
@@ -275,10 +278,10 @@ int main() {
h.fill(-10, 0);
BOOST_TEST_EQ(h.dim(), 2);
BOOST_TEST_EQ(bins(h.axis<0>()), 2);
BOOST_TEST_EQ(shape(h.axis<0>()), 4);
BOOST_TEST_EQ(bins(h.axis<1>()), 3);
BOOST_TEST_EQ(shape(h.axis<1>()), 3);
BOOST_TEST_EQ(bins(h.axis(0_c)), 2);
BOOST_TEST_EQ(shape(h.axis(0_c)), 4);
BOOST_TEST_EQ(bins(h.axis(1_c)), 3);
BOOST_TEST_EQ(shape(h.axis(1_c)), 3);
BOOST_TEST_EQ(h.sum(), 3);
BOOST_TEST_EQ(h.value(-1, 0), 0.0);
@@ -362,17 +365,17 @@ int main() {
{
auto h = make_static_histogram(integer_axis(0, 3), integer_axis(0, 4),
integer_axis(0, 5));
for (auto i = 0; i < bins(h.axis<0>()); ++i) {
for (auto j = 0; j < bins(h.axis<1>()); ++j) {
for (auto k = 0; k < bins(h.axis<2>()); ++k) {
for (auto i = 0; i < bins(h.axis(0_c)); ++i) {
for (auto j = 0; j < bins(h.axis(1_c)); ++j) {
for (auto k = 0; k < bins(h.axis(2_c)); ++k) {
h.wfill(i + j + k, i, j, k);
}
}
}
for (auto i = 0; i < bins(h.axis<0>()); ++i) {
for (auto j = 0; j < bins(h.axis<1>()); ++j) {
for (auto k = 0; k < bins(h.axis<2>()); ++k) {
for (auto i = 0; i < bins(h.axis(0_c)); ++i) {
for (auto j = 0; j < bins(h.axis(1_c)); ++j) {
for (auto k = 0; k < bins(h.axis(2_c)); ++k) {
BOOST_TEST_EQ(h.value(i, j, k), i + j + k);
}
}
@@ -488,7 +491,7 @@ int main() {
std::ostringstream os1;
// access histogram counts
for (const auto &b : h.axis<0>()) {
for (const auto &b : h.axis(0_c)) {
os1 << "bin " << b.idx << " x in [" << b.left << ", " << b.right
<< "): " << h.value(b.idx) << " +/- " << std::sqrt(h.variance(b.idx))
<< "\n";