refactoring of make_histogram factories

This commit is contained in:
Hans Dembinski
2018-11-11 13:50:27 +01:00
parent bb4afb57ec
commit fdfcf804a8
6 changed files with 94 additions and 74 deletions

View File

@@ -18,6 +18,7 @@
#include <boost/histogram/axis/variant.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/histogram/make_histogram.hpp>
#include <boost/histogram/storage_adaptor.hpp>
#include <boost/histogram/weight.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright 2015-2017 Hans Dembinski
// Copyright 2015-2018 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -9,14 +9,12 @@
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/histogram/adaptive_storage.hpp> // implements default_storage
#include <boost/histogram/arithmetic_operators.hpp>
#include <boost/histogram/detail/axes.hpp>
#include <boost/histogram/detail/index_mapper.hpp>
#include <boost/histogram/detail/meta.hpp>
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/histogram/iterator.hpp>
#include <boost/histogram/storage_adaptor.hpp>
#include <boost/mp11.hpp>
#include <functional>
#include <tuple>
@@ -26,15 +24,13 @@
namespace boost {
namespace histogram {
template <typename Axes, typename Container>
template <typename Axes, typename Storage>
class histogram {
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
public:
using axes_type = Axes;
using container_type = Container;
using storage_type =
mp11::mp_if<detail::is_storage<Container>, Container, storage_adaptor<Container>>;
using storage_type = Storage;
using value_type = typename storage_type::value_type;
using const_reference = typename storage_type::const_reference;
using const_iterator = iterator<histogram>;
@@ -45,40 +41,40 @@ public:
histogram& operator=(const histogram& rhs) = default;
histogram& operator=(histogram&& rhs) = default;
template <typename A, typename C>
explicit histogram(const histogram<A, C>& rhs) : storage_(rhs.storage_) {
template <typename A, typename S>
explicit histogram(const histogram<A, S>& rhs) : storage_(rhs.storage_) {
detail::axes_assign(axes_, rhs.axes_);
}
template <typename A, typename C>
histogram& operator=(const histogram<A, C>& rhs) {
template <typename A, typename S>
histogram& operator=(const histogram<A, S>& rhs) {
storage_ = rhs.storage_;
detail::axes_assign(axes_, rhs.axes_);
return *this;
}
explicit histogram(const axes_type& a, container_type c = container_type())
: axes_(a), storage_(std::move(c)) {
explicit histogram(const axes_type& a, storage_type s = {})
: axes_(a), storage_(std::move(s)) {
storage_.reset(detail::bincount(axes_));
}
explicit histogram(axes_type&& a, container_type c = container_type())
: axes_(std::move(a)), storage_(std::move(c)) {
explicit histogram(axes_type&& a, storage_type s = {})
: axes_(std::move(a)), storage_(std::move(s)) {
storage_.reset(detail::bincount(axes_));
}
template <typename A, typename C>
bool operator==(const histogram<A, C>& rhs) const noexcept {
template <typename A, typename S>
bool operator==(const histogram<A, S>& rhs) const noexcept {
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
}
template <typename A, typename C>
bool operator!=(const histogram<A, C>& rhs) const noexcept {
template <typename A, typename S>
bool operator!=(const histogram<A, S>& rhs) const noexcept {
return !operator==(rhs);
}
template <typename A, typename C>
histogram& operator+=(const histogram<A, C>& rhs) {
template <typename A, typename S>
histogram& operator+=(const histogram<A, S>& rhs) {
if (!detail::axes_equal(axes_, rhs.axes_))
throw std::invalid_argument("axes of histograms differ");
storage_ += rhs.storage_;
@@ -187,11 +183,10 @@ public:
using sub_axes_type = detail::sub_axes<axes_type, N, Ns...>;
using HR = histogram<sub_axes_type, storage_type>;
auto sub_axes = detail::make_sub_axes(axes_, N(), Ns()...);
// make something here to copy allocator if container has an allocator
auto hr = HR(std::move(sub_axes),
detail::static_if<detail::has_allocator<container_type>>(
[this](auto) { return container_type(storage_.get_allocator()); },
[](auto) { return container_type(); }, 0));
detail::static_if<detail::has_allocator<storage_type>>(
[this](auto) { return storage_type(storage_.get_allocator()); },
[](auto) { return storage_type(); }, 0));
const auto b = detail::bool_mask<N, Ns...>(rank(), true);
std::vector<unsigned> shape(rank());
for_each_axis(detail::shape_collector(shape.begin()));
@@ -240,50 +235,9 @@ private:
friend class histogram;
template <typename H>
friend class iterator;
friend class unsafe_access;
};
/// static type factory with custom storage type
template <typename S, typename T, typename... Ts, typename = detail::requires_axis<T>>
auto make_histogram_with(S&& s, T&& axis0, Ts&&... axis) {
auto axes = std::make_tuple(std::forward<T>(axis0), std::forward<Ts>(axis)...);
return histogram<decltype(axes), detail::unqual<S>>(std::move(axes),
std::forward<S>(s));
}
/// static type factory with standard storage type
template <typename T, typename... Ts, typename = detail::requires_axis<T>>
auto make_histogram(T&& axis0, Ts&&... axis) {
return make_histogram_with(default_storage(), std::forward<T>(axis0),
std::forward<Ts>(axis)...);
}
/// dynamic type factory from vector-like with custom storage type
template <typename S, typename T, typename = detail::requires_axis_vector<T>>
auto make_histogram_with(S&& s, T&& t) {
return histogram<detail::unqual<T>, detail::unqual<S>>(std::forward<T>(t),
std::forward<S>(s));
}
/// dynamic type factory from vector-like with standard storage type
template <typename T, typename = detail::requires_axis_vector<T>>
auto make_histogram(T&& t) {
return make_histogram_with(default_storage(), std::forward<T>(t));
}
/// dynamic type factory from iterator range with custom storage type
template <typename Storage, typename Iterator,
typename = detail::requires_iterator<Iterator>>
auto make_histogram_with(Storage&& s, Iterator begin, Iterator end) {
using T = detail::iterator_value_type<Iterator>;
auto axes = std::vector<T>(begin, end);
return make_histogram_with(std::forward<Storage>(s), std::move(axes));
}
/// dynamic type factory from iterator range with standard storage type
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
auto make_histogram(Iterator begin, Iterator end) {
return make_histogram_with(default_storage(), begin, end);
}
} // namespace histogram
} // namespace boost

View File

@@ -0,0 +1,65 @@
// Copyright 2015-2018 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_MAKE_HISTOGRAM_HPP
#define BOOST_HISTOGRAM_MAKE_HISTOGRAM_HPP
#include <boost/histogram/adaptive_storage.hpp> // implements default_storage
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/storage_adaptor.hpp>
#include <tuple>
namespace boost {
namespace histogram {
/// histogram factory from compile-time axis configuration with custom storage
template <typename C, typename T, typename... Ts, typename = detail::requires_axis<T>>
auto make_histogram_with(C&& c, T&& axis0, Ts&&... axis) {
using CU = detail::unqual<C>;
using S = mp11::mp_if<detail::is_storage<CU>, CU, storage_adaptor<CU>>;
auto axes = std::make_tuple(std::forward<T>(axis0), std::forward<Ts>(axis)...);
return histogram<decltype(axes), S>(std::move(axes), std::forward<C>(c));
}
/// histogram factory from compile-time axis configuration with standard storage
template <typename T, typename... Ts, typename = detail::requires_axis<T>>
auto make_histogram(T&& axis0, Ts&&... axis) {
return make_histogram_with(default_storage(), std::forward<T>(axis0),
std::forward<Ts>(axis)...);
}
/// histogram factory from vector-like with custom storage
template <typename C, typename T, typename = detail::requires_axis_vector<T>>
auto make_histogram_with(C&& c, T&& t) {
using CU = detail::unqual<C>;
using S = mp11::mp_if<detail::is_storage<CU>, CU, storage_adaptor<CU>>;
return histogram<detail::unqual<T>, S>(std::forward<T>(t), std::forward<C>(c));
}
/// dynamic type factory from vector-like with default storage
template <typename T, typename = detail::requires_axis_vector<T>>
auto make_histogram(T&& t) {
return make_histogram_with(default_storage(), std::forward<T>(t));
}
/// histogram factory from iterator range with custom storage
template <typename C, typename Iterator, typename = detail::requires_iterator<Iterator>>
auto make_histogram_with(C&& c, Iterator begin, Iterator end) {
using T = detail::iterator_value_type<Iterator>;
auto axes = std::vector<T>(begin, end);
return make_histogram_with(std::forward<C>(c), std::move(axes));
}
/// dynamic type factory from iterator range with default storage
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
auto make_histogram(Iterator begin, Iterator end) {
return make_histogram_with(default_storage(), begin, end);
}
} // namespace histogram
} // namespace boost
#endif

View File

@@ -8,8 +8,8 @@
#include <array>
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/adaptive_storage.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/histogram/make_histogram.hpp>
#include <boost/histogram/ostream_operators.hpp>
#include <boost/histogram/storage_adaptor.hpp>
#include <cstdlib>

View File

@@ -104,9 +104,9 @@ void run_tests() {
auto h = make(Tag(), axis::integer<>{0, 2}, axis::integer<>{0, 3});
h(0, 0);
auto h2 = decltype(h)(h);
BOOST_TEST(h2 == h);
auto h3 =
histogram<std::tuple<axis::integer<>, axis::integer<>>, std::vector<unsigned>>(h);
BOOST_TEST_EQ(h2, h);
auto h3 = histogram<std::tuple<axis::integer<>, axis::integer<>>,
storage_adaptor<std::vector<unsigned>>>(h);
BOOST_TEST_EQ(h3, h);
}
@@ -121,8 +121,8 @@ void run_tests() {
// test self-assign
h2 = h2;
BOOST_TEST_EQ(h, h2);
auto h3 =
histogram<std::tuple<axis::integer<>, axis::integer<>>, std::vector<unsigned>>();
auto h3 = histogram<std::tuple<axis::integer<>, axis::integer<>>,
storage_adaptor<std::vector<unsigned>>>();
h3 = h;
BOOST_TEST_EQ(h, h3);
}

View File

@@ -8,7 +8,7 @@
#define BOOST_HISTOGRAM_TEST_UTILITY_HISTOGRAM_HPP
#include <boost/histogram/axis/variant.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/make_histogram.hpp>
#include <numeric>
#include <ostream>
#include <type_traits>