mirror of
https://github.com/boostorg/histogram.git
synced 2026-02-22 15:32:12 +00:00
unified both histogram classes
This commit is contained in:
@@ -8,8 +8,7 @@
|
||||
#define BOOST_HISTOGRAM_HPP_
|
||||
|
||||
#include <boost/histogram/axis.hpp>
|
||||
#include <boost/histogram/dynamic_histogram.hpp>
|
||||
#include <boost/histogram/static_histogram.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
#include <boost/histogram/storage/container_storage.hpp>
|
||||
#include <boost/histogram/utility.hpp>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <boost/histogram/detail/utility.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
@@ -19,12 +19,11 @@ namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <typename T> struct has_weight_support {
|
||||
template <typename T> struct has_variance {
|
||||
template <typename> static std::false_type test(...);
|
||||
|
||||
template <typename C>
|
||||
static decltype(std::declval<C &>().increase(0, 0.0),
|
||||
std::declval<C &>().variance(0), std::true_type{})
|
||||
static decltype(std::declval<C &>().variance(0), std::true_type{})
|
||||
test(int);
|
||||
|
||||
static bool const value = decltype(test<T>(0))::value;
|
||||
@@ -43,11 +42,6 @@ template <typename T, typename = decltype(std::begin(std::declval<T &>()),
|
||||
std::end(std::declval<T &>()))>
|
||||
struct is_sequence {};
|
||||
|
||||
struct histogram_tag {};
|
||||
|
||||
template <typename T, typename = typename T::histogram_tag>
|
||||
struct is_histogram {};
|
||||
|
||||
template <typename S1, typename S2> struct intersection {
|
||||
using type = typename std::conditional<
|
||||
mpl::equal<S1, S2>::value, S1,
|
||||
@@ -55,25 +49,6 @@ template <typename S1, typename S2> struct intersection {
|
||||
type;
|
||||
};
|
||||
|
||||
// // prefer dynamic over static storage, choose
|
||||
// // static_storage with larger capacity
|
||||
// template <typename Storage1,
|
||||
// typename Storage2>
|
||||
// struct select_storage {
|
||||
// using type = typename std::conditional<
|
||||
// (is_dynamic_storage<Storage1>::value ||
|
||||
// is_dynamic_storage<Storage2>::value),
|
||||
// typename std::conditional<
|
||||
// is_dynamic_storage<Storage1>::value,
|
||||
// Storage1, Storage2
|
||||
// >::type,
|
||||
// typename std::conditional<
|
||||
// (std::numeric_limits<typename Storage1::value_t>::max() >
|
||||
// std::numeric_limits<typename Storage2::value_t>::max()),
|
||||
// Storage1, Storage2
|
||||
// >::type
|
||||
// >::type;
|
||||
// };
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace detail {
|
||||
|
||||
namespace {
|
||||
template <typename Storage>
|
||||
typename std::enable_if<has_weight_support<Storage>::value,
|
||||
typename std::enable_if<has_variance<Storage>::value,
|
||||
typename Storage::value_type>::type
|
||||
variance_impl(const Storage &s, std::size_t i) {
|
||||
return s.variance(i);
|
||||
} // delegate to Storage implementation
|
||||
|
||||
template <typename Storage>
|
||||
typename std::enable_if<!(has_weight_support<Storage>::value),
|
||||
typename std::enable_if<!(has_variance<Storage>::value),
|
||||
typename Storage::value_type>::type
|
||||
variance_impl(const Storage &s, std::size_t i) {
|
||||
return s.value(i);
|
||||
|
||||
14
include/boost/histogram/histogram.hpp
Normal file
14
include/boost/histogram/histogram.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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_HISTOGRAM_HPP_
|
||||
#define _BOOST_HISTOGRAM_HISTOGRAM_HPP_
|
||||
|
||||
#include <boost/histogram/histogram_fwd.hpp>
|
||||
#include <boost/histogram/histogram_static_impl.hpp>
|
||||
#include <boost/histogram/histogram_dynamic_impl.hpp>
|
||||
|
||||
#endif
|
||||
@@ -4,18 +4,17 @@
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef _BOOST_HISTOGRAM_DYNAMIC_HISTOGRAM_HPP_
|
||||
#define _BOOST_HISTOGRAM_DYNAMIC_HISTOGRAM_HPP_
|
||||
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_DYNAMIC_IMPL_HPP_
|
||||
#define _BOOST_HISTOGRAM_HISTOGRAM_DYNAMIC_IMPL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/histogram/histogram_fwd.hpp>
|
||||
#include <boost/histogram/axis.hpp>
|
||||
#include <boost/histogram/detail/axis_visitor.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/detail/utility.hpp>
|
||||
#include <boost/histogram/detail/variance.hpp>
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
#include <boost/mpl/empty.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
@@ -28,12 +27,11 @@
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <typename Axes = default_axes, typename Storage = adaptive_storage<>>
|
||||
class dynamic_histogram {
|
||||
template <typename Axes, typename Storage>
|
||||
class histogram<true, Axes, Storage> {
|
||||
static_assert(!mpl::empty<Axes>::value, "at least one axis required");
|
||||
using pairs = std::pair<std::size_t, std::size_t>;
|
||||
using size_pair = std::pair<std::size_t, std::size_t>;
|
||||
public:
|
||||
using histogram_tag = detail::histogram_tag;
|
||||
using axis_type = typename make_variant_over<Axes>::type;
|
||||
using value_type = typename Storage::value_type;
|
||||
|
||||
@@ -41,34 +39,34 @@ private:
|
||||
using axes_type = std::vector<axis_type>;
|
||||
|
||||
public:
|
||||
dynamic_histogram() = default;
|
||||
histogram() = default;
|
||||
|
||||
template <typename... Axes1>
|
||||
explicit dynamic_histogram(const Axes1 &... axes)
|
||||
explicit histogram(const Axes1 &... axes)
|
||||
: axes_({axis_type(axes)...}) {
|
||||
storage_ = Storage(field_count());
|
||||
}
|
||||
|
||||
template <typename Iterator, typename = detail::is_iterator<Iterator>>
|
||||
dynamic_histogram(Iterator axes_begin, Iterator axes_end)
|
||||
histogram(Iterator axes_begin, Iterator axes_end)
|
||||
: axes_(std::distance(axes_begin, axes_end)) {
|
||||
std::copy(axes_begin, axes_end, axes_.begin());
|
||||
storage_ = Storage(field_count());
|
||||
}
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
explicit dynamic_histogram(
|
||||
const dynamic_histogram<OtherAxes, OtherStorage> &other)
|
||||
explicit histogram(
|
||||
const histogram<true, OtherAxes, OtherStorage> &other)
|
||||
: axes_(other.axes_.begin(), other.axes_.end()),
|
||||
storage_(other.storage_) {}
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
explicit dynamic_histogram(dynamic_histogram<OtherAxes, OtherStorage> &&other)
|
||||
explicit histogram(histogram<true, OtherAxes, OtherStorage> &&other)
|
||||
: axes_(std::move(other.axes_)), storage_(std::move(other.storage_)) {}
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
dynamic_histogram &
|
||||
operator=(const dynamic_histogram<OtherAxes, OtherStorage> &other) {
|
||||
histogram &
|
||||
operator=(const histogram<true, OtherAxes, OtherStorage> &other) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&other)) {
|
||||
axes_ = other.axes_;
|
||||
storage_ = other.storage_;
|
||||
@@ -77,8 +75,8 @@ public:
|
||||
}
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
dynamic_histogram &
|
||||
operator=(dynamic_histogram<OtherAxes, OtherStorage> &&other) {
|
||||
histogram &
|
||||
operator=(histogram<true, OtherAxes, OtherStorage> &&other) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&other)) {
|
||||
axes_ = std::move(other.axes_);
|
||||
storage_ = std::move(other.storage_);
|
||||
@@ -88,7 +86,7 @@ public:
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
bool
|
||||
operator==(const dynamic_histogram<OtherAxes, OtherStorage> &other) const {
|
||||
operator==(const histogram<true, OtherAxes, OtherStorage> &other) const {
|
||||
if (mpl::empty<
|
||||
typename detail::intersection<Axes, OtherAxes>::type>::value) {
|
||||
return false;
|
||||
@@ -105,13 +103,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
template <template <class, class> class Histogram, typename OtherAxes,
|
||||
typename OtherStorage>
|
||||
dynamic_histogram &
|
||||
operator+=(const Histogram<OtherAxes, OtherStorage> &other) {
|
||||
template <bool D, typename A, typename S>
|
||||
histogram &
|
||||
operator+=(const histogram<D, A, S> &other) {
|
||||
static_assert(
|
||||
!mpl::empty<
|
||||
typename detail::intersection<Axes, OtherAxes>::type>::value,
|
||||
typename detail::intersection<Axes, A>::type>::value,
|
||||
"histograms lack common axes types");
|
||||
if (dim() != other.dim()) {
|
||||
throw std::logic_error("dimensions of histograms differ");
|
||||
@@ -129,7 +126,7 @@ public:
|
||||
template <typename... Values> void fill(Values... values) {
|
||||
BOOST_ASSERT_MSG(sizeof...(values) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::xlin, Values...>(pairs(0, 1), values...);
|
||||
const auto p = apply_lin<detail::xlin, Values...>(size_pair(0, 1), values...);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first);
|
||||
}
|
||||
@@ -139,33 +136,27 @@ public:
|
||||
void fill(Iterator begin, Iterator end) {
|
||||
BOOST_ASSERT_MSG(std::distance(begin, end) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin_iter<detail::xlin>(pairs(0, 1), begin);
|
||||
const auto p = apply_lin_iter<detail::xlin>(size_pair(0, 1), begin);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
bool has_weight_support = detail::has_weight_support<Storage>::value,
|
||||
typename... Values>
|
||||
typename std::enable_if<has_weight_support>::type wfill(value_type w,
|
||||
Values... values) {
|
||||
template <typename... Values>
|
||||
void wfill(value_type w, Values... values) {
|
||||
BOOST_ASSERT_MSG(sizeof...(values) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::xlin, Values...>(pairs(0, 1), values...);
|
||||
const auto p = apply_lin<detail::xlin, Values...>(size_pair(0, 1), values...);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first, w);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
bool has_weight_support = detail::has_weight_support<Storage>::value,
|
||||
typename Iterator, typename = detail::is_iterator<Iterator>>
|
||||
typename std::enable_if<has_weight_support>::type
|
||||
wfill(value_type w, Iterator begin, Iterator end) {
|
||||
template <typename Iterator, typename = detail::is_iterator<Iterator>>
|
||||
void wfill(value_type w, Iterator begin, Iterator end) {
|
||||
BOOST_ASSERT_MSG(std::distance(begin, end) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin_iter<detail::xlin>(pairs(0, 1), begin);
|
||||
const auto p = apply_lin_iter<detail::xlin>(size_pair(0, 1), begin);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first, w);
|
||||
}
|
||||
@@ -174,7 +165,7 @@ public:
|
||||
template <typename... Indices> value_type value(Indices... indices) const {
|
||||
BOOST_ASSERT_MSG(sizeof...(indices) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::lin, Indices...>(pairs(0, 1), indices...);
|
||||
const auto p = apply_lin<detail::lin, Indices...>(size_pair(0, 1), indices...);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
@@ -185,7 +176,7 @@ public:
|
||||
value_type value(Iterator begin, Iterator end) const {
|
||||
BOOST_ASSERT_MSG(std::distance(begin, end) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin_iter<detail::lin>(pairs(0, 1), begin);
|
||||
const auto p = apply_lin_iter<detail::lin>(size_pair(0, 1), begin);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
@@ -193,24 +184,26 @@ public:
|
||||
}
|
||||
|
||||
template <typename... Indices> value_type variance(Indices... indices) const {
|
||||
static_assert(detail::has_variance<Storage>::value, "Storage lacks variance support");
|
||||
BOOST_ASSERT_MSG(sizeof...(indices) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::lin, Indices...>(pairs(0, 1), indices...);
|
||||
const auto p = apply_lin<detail::lin, Indices...>(size_pair(0, 1), indices...);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
return detail::variance(storage_, p.first);
|
||||
return storage_.variance(p.first);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename = detail::is_iterator<Iterator>>
|
||||
value_type variance(Iterator begin, Iterator end) const {
|
||||
static_assert(detail::has_variance<Storage>::value, "Storage lacks variance support");
|
||||
BOOST_ASSERT_MSG(std::distance(begin, end) == dim(),
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin_iter<detail::lin>(pairs(0, 1), begin);
|
||||
const auto p = apply_lin_iter<detail::lin>(size_pair(0, 1), begin);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
return detail::variance(storage_, p.first);
|
||||
return storage_.variance(p.first);
|
||||
}
|
||||
|
||||
/// Number of axes (dimensions) of histogram
|
||||
@@ -271,19 +264,19 @@ private:
|
||||
}
|
||||
|
||||
template <template <class, class> class Lin, typename Value>
|
||||
struct lin_visitor : public static_visitor<pairs> {
|
||||
mutable pairs pa;
|
||||
struct lin_visitor : public static_visitor<size_pair> {
|
||||
mutable size_pair pa;
|
||||
const Value &val;
|
||||
lin_visitor(const pairs& p, const Value &v)
|
||||
lin_visitor(const size_pair& p, const Value &v)
|
||||
: pa(p), val(v) {}
|
||||
template <typename A> pairs operator()(const A &a) const {
|
||||
template <typename A> size_pair operator()(const A &a) const {
|
||||
Lin<A, Value>::apply(pa.first, pa.second, a, val);
|
||||
return pa;
|
||||
}
|
||||
};
|
||||
|
||||
template <template <class, class> class Lin, typename First, typename... Rest>
|
||||
pairs apply_lin(pairs&& p, const First &first,
|
||||
size_pair apply_lin(size_pair&& p, const First &first,
|
||||
const Rest &... rest) const {
|
||||
p = apply_visitor(lin_visitor<Lin, First>(p, first),
|
||||
axes_[dim() - 1 - sizeof...(Rest)]);
|
||||
@@ -291,10 +284,10 @@ private:
|
||||
}
|
||||
|
||||
template <template <class, class> class Lin>
|
||||
pairs apply_lin(pairs&& p) const { return p; }
|
||||
size_pair apply_lin(size_pair&& p) const { return p; }
|
||||
|
||||
template <template <class, class> class Lin, typename Iterator>
|
||||
pairs apply_lin_iter(pairs&& p, Iterator iter) const {
|
||||
size_pair apply_lin_iter(size_pair&& p, Iterator iter) const {
|
||||
for (const auto &a : axes_) {
|
||||
p = apply_visitor(lin_visitor<Lin, decltype(*iter)>(p, *iter), a);
|
||||
++iter;
|
||||
@@ -304,23 +297,23 @@ private:
|
||||
|
||||
friend struct storage_access;
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
friend class dynamic_histogram;
|
||||
template <bool D, typename A, typename S>
|
||||
friend class histogram;
|
||||
|
||||
template <typename Archiv, typename OtherAxes, typename OtherStorage>
|
||||
friend void serialize(Archiv &, dynamic_histogram<OtherAxes, OtherStorage> &,
|
||||
template <typename Archiv, typename A, typename S>
|
||||
friend void serialize(Archiv &, histogram<true, A, S> &,
|
||||
unsigned);
|
||||
};
|
||||
|
||||
template <typename... Axes>
|
||||
inline dynamic_histogram<> make_dynamic_histogram(Axes &&... axes) {
|
||||
return dynamic_histogram<>(std::forward<Axes>(axes)...);
|
||||
inline histogram<true, default_axes> make_dynamic_histogram(Axes &&... axes) {
|
||||
return histogram<true, default_axes>(std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
template <typename Storage, typename... Axes>
|
||||
inline dynamic_histogram<default_axes, Storage>
|
||||
inline histogram<true, default_axes, Storage>
|
||||
make_dynamic_histogram_with(Axes &&... axes) {
|
||||
return dynamic_histogram<default_axes, Storage>(std::forward<Axes>(axes)...);
|
||||
return histogram<true, default_axes, Storage>(std::forward<Axes>(axes)...);
|
||||
}
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
22
include/boost/histogram/histogram_fwd.hpp
Normal file
22
include/boost/histogram/histogram_fwd.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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_HISTOGRAM_FWD_HPP_
|
||||
#define _BOOST_HISTOGRAM_HISTOGRAM_FWD_HPP_
|
||||
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <bool Dynamic,
|
||||
class Axes,
|
||||
class Storage = adaptive_storage<> > class histogram;
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -8,8 +8,7 @@
|
||||
#define _BOOST_HISTOGRAM_HISTOGRAM_OSTREAM_OPERATORS_HPP_
|
||||
|
||||
#include <boost/histogram/axis_ostream_operators.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/utility.hpp>
|
||||
#include <boost/histogram/histogram_fwd.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace boost {
|
||||
@@ -25,11 +24,9 @@ struct axis_ostream_visitor {
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <template <typename, typename> class Histogram, typename Axes,
|
||||
typename Storage,
|
||||
typename = detail::is_histogram<Histogram<Axes, Storage>>>
|
||||
template <bool D, typename A, typename S>
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const Histogram<Axes, Storage> &h) {
|
||||
const histogram<D, A, S> &h) {
|
||||
os << "histogram(";
|
||||
detail::axis_ostream_visitor sh(os);
|
||||
h.for_each_axis(sh);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2015-2016 Hans Dembinski
|
||||
// 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_STATIC_HISTOGRAM_HPP_
|
||||
#define _BOOST_HISTOGRAM_STATIC_HISTOGRAM_HPP_
|
||||
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_STATIC_IMPL_HPP_
|
||||
#define _BOOST_HISTOGRAM_HISTOGRAM_STATIC_IMPL_HPP_
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/fusion/adapted/mpl.hpp>
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <boost/fusion/include/sequence.hpp>
|
||||
#include <boost/fusion/sequence.hpp>
|
||||
#include <boost/fusion/sequence/comparison.hpp>
|
||||
#include <boost/histogram/histogram_fwd.hpp>
|
||||
#include <boost/histogram/axis.hpp>
|
||||
#include <boost/histogram/detail/axis_visitor.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/detail/utility.hpp>
|
||||
#include <boost/histogram/detail/variance.hpp>
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
#include <boost/mpl/empty.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
@@ -31,42 +31,41 @@
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <typename Axes, typename Storage = adaptive_storage<>>
|
||||
class static_histogram {
|
||||
template <typename Axes, typename Storage>
|
||||
class histogram<false, Axes, Storage> {
|
||||
static_assert(!mpl::empty<Axes>::value, "at least one axis required");
|
||||
using pairs = std::pair<std::size_t, std::size_t>;
|
||||
|
||||
using size_pair = std::pair<std::size_t, std::size_t>;
|
||||
using axes_size = typename fusion::result_of::size<Axes>::type;
|
||||
public:
|
||||
using histogram_tag = detail::histogram_tag;
|
||||
using value_type = typename Storage::value_type;
|
||||
|
||||
private:
|
||||
using axes_type = typename fusion::result_of::as_vector<Axes>::type;
|
||||
|
||||
public:
|
||||
static_histogram() = default;
|
||||
histogram() = default;
|
||||
|
||||
template <typename... Axes1>
|
||||
explicit static_histogram(const Axes1 &... axes) : axes_(axes...) {
|
||||
explicit histogram(const Axes1 &... axes) : axes_(axes...) {
|
||||
storage_ = Storage(field_count());
|
||||
}
|
||||
|
||||
static_histogram(const static_histogram &other) = default;
|
||||
static_histogram(static_histogram &&other) = default;
|
||||
static_histogram &operator=(const static_histogram &other) = default;
|
||||
static_histogram &operator=(static_histogram &&other) = default;
|
||||
histogram(const histogram &other) = default;
|
||||
histogram(histogram &&other) = default;
|
||||
histogram &operator=(const histogram &other) = default;
|
||||
histogram &operator=(histogram &&other) = default;
|
||||
|
||||
template <typename OtherStorage>
|
||||
explicit static_histogram(const static_histogram<Axes, OtherStorage> &other)
|
||||
template <typename S>
|
||||
explicit histogram(const histogram<false, Axes, S> &other)
|
||||
: axes_(other.axes_), storage_(other.storage_) {}
|
||||
|
||||
template <typename OtherStorage>
|
||||
explicit static_histogram(static_histogram<Axes, OtherStorage> &&other)
|
||||
template <typename S>
|
||||
explicit histogram(histogram<false, Axes, S> &&other)
|
||||
: axes_(std::move(other.axes_)), storage_(std::move(other.storage_)) {}
|
||||
|
||||
template <typename OtherStorage>
|
||||
static_histogram &
|
||||
operator=(const static_histogram<Axes, OtherStorage> &other) {
|
||||
template <typename S>
|
||||
histogram &
|
||||
operator=(const histogram<false, Axes, S> &other) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&other)) {
|
||||
axes_ = other.axes_;
|
||||
storage_ = other.storage_;
|
||||
@@ -74,8 +73,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherStorage>
|
||||
static_histogram &operator=(static_histogram<Axes, OtherStorage> &&other) {
|
||||
template <typename S>
|
||||
histogram &operator=(histogram<false, Axes, S> &&other) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&other)) {
|
||||
axes_ = std::move(other.axes_);
|
||||
storage_ = std::move(other.storage_);
|
||||
@@ -83,18 +82,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
template <typename A, typename S>
|
||||
bool
|
||||
operator==(const static_histogram<OtherAxes, OtherStorage> &other) const {
|
||||
operator==(const histogram<false, A, S> &other) const {
|
||||
if (!axes_equal_to(other.axes_)) {
|
||||
return false;
|
||||
}
|
||||
return storage_ == other.storage_;
|
||||
}
|
||||
|
||||
template <typename OtherStorage>
|
||||
static_histogram &
|
||||
operator+=(const static_histogram<Axes, OtherStorage> &other) {
|
||||
template <typename S>
|
||||
histogram &
|
||||
operator+=(const histogram<false, Axes, S> &other) {
|
||||
if (!axes_equal_to(other.axes_)) {
|
||||
throw std::logic_error("axes of histograms differ");
|
||||
}
|
||||
@@ -103,31 +102,27 @@ public:
|
||||
}
|
||||
|
||||
template <typename... Values> void fill(Values... values) {
|
||||
static_assert(sizeof...(values) == dim(),
|
||||
static_assert(sizeof...(values) == axes_size::value,
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::xlin, Values...>(pairs(0, 1), values...);
|
||||
const auto p = apply_lin<detail::xlin, Values...>(size_pair(0, 1), values...);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
bool has_weight_support = detail::has_weight_support<Storage>::value,
|
||||
typename... Values>
|
||||
typename std::enable_if<has_weight_support>::type wfill(value_type w,
|
||||
Values... values) {
|
||||
static_assert(sizeof...(values) == dim(),
|
||||
template <typename... Values> void wfill(value_type w, Values... values) {
|
||||
static_assert(sizeof...(values) == axes_size::value,
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::xlin, Values...>(pairs(0, 1), values...);
|
||||
const auto p = apply_lin<detail::xlin, Values...>(size_pair(0, 1), values...);
|
||||
if (p.second) {
|
||||
storage_.increase(p.first, w);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Indices> value_type value(Indices... indices) const {
|
||||
static_assert(sizeof...(indices) == dim(),
|
||||
static_assert(sizeof...(indices) == axes_size::value,
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::lin, Indices...>(pairs(0, 1), indices...);
|
||||
const auto p = apply_lin<detail::lin, Indices...>(size_pair(0, 1), indices...);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
@@ -135,19 +130,18 @@ public:
|
||||
}
|
||||
|
||||
template <typename... Indices> value_type variance(Indices... indices) const {
|
||||
static_assert(sizeof...(indices) == dim(),
|
||||
static_assert(detail::has_variance<Storage>::value, "Storage lacks variance support");
|
||||
static_assert(sizeof...(indices) == axes_size::value,
|
||||
"number of arguments does not match histogram dimension");
|
||||
const auto p = apply_lin<detail::lin, Indices...>(pairs(0, 1), indices...);
|
||||
const auto p = apply_lin<detail::lin, Indices...>(size_pair(0, 1), indices...);
|
||||
if (p.second == 0) {
|
||||
throw std::out_of_range("invalid index");
|
||||
}
|
||||
return detail::variance(storage_, p.first);
|
||||
return storage_.variance(p.first);
|
||||
}
|
||||
|
||||
/// Number of axes (dimensions) of histogram
|
||||
static constexpr unsigned dim() {
|
||||
return fusion::result_of::size<Axes>::type::value;
|
||||
}
|
||||
constexpr unsigned dim() const { return axes_size::value; }
|
||||
|
||||
/// Total number of bins in the histogram (including underflow/overflow)
|
||||
std::size_t size() const { return storage_.size(); }
|
||||
@@ -165,8 +159,7 @@ public:
|
||||
typename std::add_const<
|
||||
typename fusion::result_of::value_at_c<axes_type, N>::type>::type &
|
||||
axis() const {
|
||||
static_assert(N < fusion::result_of::size<axes_type>::value,
|
||||
"axis index out of range");
|
||||
static_assert(N < axes_size::value, "axis index out of range");
|
||||
return fusion::at_c<N>(axes_);
|
||||
}
|
||||
|
||||
@@ -185,8 +178,8 @@ private:
|
||||
return fc.value;
|
||||
}
|
||||
|
||||
template <typename OtherAxes>
|
||||
bool axes_equal_to(const OtherAxes & /*unused*/) const {
|
||||
template <typename A>
|
||||
bool axes_equal_to(const A & /*unused*/) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -195,38 +188,38 @@ private:
|
||||
}
|
||||
|
||||
template <template <class, class> class Lin, typename First, typename... Rest>
|
||||
pairs apply_lin(pairs&& p, const First &x,
|
||||
size_pair apply_lin(size_pair&& p, const First &x,
|
||||
const Rest &... rest) const {
|
||||
Lin<typename fusion::result_of::value_at_c<
|
||||
axes_type, (dim() - 1 - sizeof...(Rest))>::type,
|
||||
axes_type, (axes_size::value - 1 - sizeof...(Rest))>::type,
|
||||
First>::apply(p.first, p.second,
|
||||
fusion::at_c<(dim() - 1 - sizeof...(Rest))>(axes_), x);
|
||||
fusion::at_c<(axes_size::value - 1 - sizeof...(Rest))>(axes_), x);
|
||||
return apply_lin<Lin, Rest...>(std::move(p), rest...);
|
||||
}
|
||||
|
||||
template <template <class, class> class Lin>
|
||||
pairs apply_lin(pairs&& p) const { return p; }
|
||||
size_pair apply_lin(size_pair&& p) const { return p; }
|
||||
|
||||
template <typename OtherAxes, typename OtherStorage>
|
||||
friend class static_histogram;
|
||||
template <bool D, typename A, typename S>
|
||||
friend class histogram;
|
||||
|
||||
template <class Archive, class OtherStorage, class OtherAxes>
|
||||
friend void serialize(Archive &, static_histogram<OtherStorage, OtherAxes> &,
|
||||
template <class Archive, class S, class A>
|
||||
friend void serialize(Archive &, histogram<false, S, A> &,
|
||||
unsigned);
|
||||
};
|
||||
|
||||
/// default static type factory
|
||||
template <typename... Axes>
|
||||
inline static_histogram<mpl::vector<Axes...>>
|
||||
inline histogram<false, mpl::vector<Axes...>>
|
||||
make_static_histogram(const Axes &... axes) {
|
||||
return static_histogram<mpl::vector<Axes...>>(axes...);
|
||||
return histogram<false, mpl::vector<Axes...>>(axes...);
|
||||
}
|
||||
|
||||
/// static type factory with variable storage type
|
||||
template <typename Storage, typename... Axes>
|
||||
inline static_histogram<mpl::vector<Axes...>, Storage>
|
||||
inline histogram<false, mpl::vector<Axes...>, Storage>
|
||||
make_static_histogram_with(const Axes &... axes) {
|
||||
return static_histogram<mpl::vector<Axes...>, Storage>(axes...);
|
||||
return histogram<false, mpl::vector<Axes...>, Storage>(axes...);
|
||||
}
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
@@ -11,8 +11,7 @@
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/histogram/detail/utility.hpp>
|
||||
#include <boost/histogram/detail/weight.hpp>
|
||||
#include <boost/histogram/dynamic_histogram.hpp>
|
||||
#include <boost/histogram/static_histogram.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
#include <boost/histogram/storage/container_storage.hpp>
|
||||
#include <boost/serialization/array.hpp>
|
||||
@@ -177,16 +176,16 @@ template <typename Archive> struct serialize_helper {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template <class Archive, class Storage, class Axes>
|
||||
inline void serialize(Archive &ar, static_histogram<Storage, Axes> &h,
|
||||
template <class Archive, class S, class A>
|
||||
inline void serialize(Archive &ar, histogram<false, S, A> &h,
|
||||
unsigned /* version */) {
|
||||
serialize_helper<Archive> sh(ar);
|
||||
fusion::for_each(h.axes_, sh);
|
||||
ar &h.storage_;
|
||||
}
|
||||
|
||||
template <class Archive, class Storage, class Axes>
|
||||
inline void serialize(Archive &ar, dynamic_histogram<Storage, Axes> &h,
|
||||
template <class Archive, class S, class A>
|
||||
inline void serialize(Archive &ar, histogram<true, S, A> &h,
|
||||
unsigned /* version */) {
|
||||
ar &h.axes_;
|
||||
ar &h.storage_;
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OtherStorage, typename = detail::is_storage<OtherStorage>>
|
||||
template <typename OtherStorage>
|
||||
adaptive_storage &operator=(const OtherStorage &rhs) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
|
||||
if (size() != rhs.size()) {
|
||||
@@ -193,7 +193,7 @@ public:
|
||||
return apply_visitor(variance_visitor(i), buffer_);
|
||||
}
|
||||
|
||||
template <typename OtherStorage, typename = detail::is_storage<OtherStorage>>
|
||||
template <typename OtherStorage>
|
||||
adaptive_storage &operator+=(const OtherStorage &rhs) {
|
||||
for (std::size_t i = 0, n = rhs.size(); i < n; ++i)
|
||||
apply_visitor(add_visitor<typename OtherStorage::value_type>(
|
||||
@@ -206,7 +206,7 @@ public:
|
||||
return apply_visitor(bicmp_visitor(), buffer_, o.buffer_);
|
||||
}
|
||||
|
||||
template <typename OtherStorage, typename = detail::is_storage<OtherStorage>>
|
||||
template <typename OtherStorage>
|
||||
bool operator==(const OtherStorage &o) const {
|
||||
return apply_visitor(cmp_visitor<OtherStorage>(o), buffer_);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OtherStorage, typename = detail::is_storage<OtherStorage>>
|
||||
template <typename OtherStorage>
|
||||
container_storage &operator=(const OtherStorage &other) {
|
||||
detail::init(container_, other.size());
|
||||
for (std::size_t i = 0; i < container_.size(); ++i) {
|
||||
@@ -61,9 +61,10 @@ public:
|
||||
|
||||
std::size_t size() const { return container_.size(); }
|
||||
void increase(std::size_t i) { ++(container_[i]); }
|
||||
void increase(std::size_t i, value_type w) { container_[i] += w; }
|
||||
value_type value(std::size_t i) const { return container_[i]; }
|
||||
|
||||
template <typename OtherStorage, typename = detail::is_storage<OtherStorage>>
|
||||
template <typename OtherStorage>
|
||||
void operator+=(const OtherStorage &other) {
|
||||
for (std::size_t i = 0; i < container_.size(); ++i) {
|
||||
container_[i] += other.value(i);
|
||||
|
||||
Reference in New Issue
Block a user