mirror of
https://github.com/boostorg/histogram.git
synced 2026-01-29 07:32:23 +00:00
work in progress
This commit is contained in:
@@ -96,6 +96,16 @@ struct lower : public static_visitor<double> {
|
||||
}
|
||||
};
|
||||
|
||||
struct bicmp : public static_visitor<bool> {
|
||||
template <typename T, typename U> bool operator()(const T& t, const U& u) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> bool operator()(const T& t, const T& u) const {
|
||||
return t == u;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Polymorphic axis type
|
||||
@@ -164,6 +174,11 @@ public:
|
||||
return base_type::operator==(static_cast<const base_type &>(rhs));
|
||||
}
|
||||
|
||||
template <typename... Us>
|
||||
bool operator==(const any<Us...>& rhs) const {
|
||||
return apply_visitor(detail::bicmp(), *this, rhs);
|
||||
}
|
||||
|
||||
const_iterator begin() const { return const_iterator(*this, 0); }
|
||||
const_iterator end() const { return const_iterator(*this, size()); }
|
||||
const_reverse_iterator rbegin() const {
|
||||
|
||||
@@ -40,9 +40,9 @@ namespace axis {
|
||||
enum class uoflow { off = false, on = true };
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# define BOOST_HISTOGRAM_ENUM_CLASS enum class
|
||||
# define BOOST_HISTOGRAM_ENUM_CLASS_ARG enum class
|
||||
#else
|
||||
# define BOOST_HISTOGRAM_ENUM_CLASS enum
|
||||
# define BOOST_HISTOGRAM_ENUM_CLASS_ARG enum
|
||||
#endif
|
||||
|
||||
/// Base class for all axes, uses CRTP to inject iterator logic.
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
inline bool uoflow() const noexcept { return shape_ > base_type::size(); }
|
||||
|
||||
protected:
|
||||
axis_base_uoflow(unsigned n, string_view label, BOOST_HISTOGRAM_ENUM_CLASS uoflow uo)
|
||||
axis_base_uoflow(unsigned n, string_view label, BOOST_HISTOGRAM_ENUM_CLASS_ARG uoflow uo)
|
||||
: base_type(n, label), shape_(n + 2 * static_cast<int>(uo)) {}
|
||||
|
||||
axis_base_uoflow() = default;
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
*/
|
||||
regular(unsigned n, value_type lower, value_type upper,
|
||||
string_view label = {},
|
||||
BOOST_HISTOGRAM_ENUM_CLASS uoflow uo = ::boost::histogram::axis::uoflow::on,
|
||||
BOOST_HISTOGRAM_ENUM_CLASS_ARG uoflow uo = ::boost::histogram::axis::uoflow::on,
|
||||
Transform trans = Transform())
|
||||
: base_type(n, label, uo), Transform(trans), min_(trans.forward(lower)),
|
||||
delta_((trans.forward(upper) - trans.forward(lower)) / n) {
|
||||
@@ -372,7 +372,7 @@ public:
|
||||
* \param uoflow whether to add under-/overflow bins.
|
||||
*/
|
||||
variable(std::initializer_list<value_type> x, string_view label = {},
|
||||
BOOST_HISTOGRAM_ENUM_CLASS uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
BOOST_HISTOGRAM_ENUM_CLASS_ARG uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
: base_type(x.size() - 1, label, uo), x_(new value_type[x.size()]) {
|
||||
if (x.size() >= 2) {
|
||||
std::copy(x.begin(), x.end(), x_.get());
|
||||
@@ -384,7 +384,7 @@ public:
|
||||
|
||||
template <typename Iterator>
|
||||
variable(Iterator begin, Iterator end, string_view label = {},
|
||||
BOOST_HISTOGRAM_ENUM_CLASS uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
BOOST_HISTOGRAM_ENUM_CLASS_ARG uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
: base_type(std::distance(begin, end) - 1, label, uo),
|
||||
x_(new value_type[std::distance(begin, end)]) {
|
||||
std::copy(begin, end, x_.get());
|
||||
@@ -461,7 +461,7 @@ public:
|
||||
* \param uoflow whether to add under-/overflow bins.
|
||||
*/
|
||||
integer(value_type lower, value_type upper, string_view label = {},
|
||||
BOOST_HISTOGRAM_ENUM_CLASS uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
BOOST_HISTOGRAM_ENUM_CLASS_ARG uoflow uo = ::boost::histogram::axis::uoflow::on)
|
||||
: base_type(upper - lower, label, uo), min_(lower) {
|
||||
if (!(lower < upper)) {
|
||||
throw std::invalid_argument("lower < upper required");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/histogram/axis/any.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
|
||||
@@ -71,49 +71,28 @@ template <typename T,
|
||||
typename = decltype(*std::declval<T &>(), ++std::declval<T &>())>
|
||||
struct requires_iterator {};
|
||||
|
||||
template <typename L1, typename L2>
|
||||
using union_t = mp11::mp_unique<mp11::mp_append<L1, L2>>;
|
||||
template <typename T>
|
||||
using requires_axis = decltype(std::declval<T &>().size(),
|
||||
std::declval<T &>().shape(),
|
||||
std::declval<T &>().uoflow(),
|
||||
std::declval<T &>().label(),
|
||||
std::declval<T &>()[0]);
|
||||
|
||||
struct bool_mask_op {
|
||||
std::vector<bool> &b;
|
||||
bool v;
|
||||
template <typename N> void operator()(const N &) const { b[N::value] = v; }
|
||||
};
|
||||
namespace {
|
||||
struct bool_mask_impl {
|
||||
std::vector<bool> &b;
|
||||
bool v;
|
||||
template <typename Int> void operator()(Int) const { b[Int::value] = v; }
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Ns> std::vector<bool> bool_mask(unsigned n, bool v) {
|
||||
template <typename... Ns>
|
||||
std::vector<bool> bool_mask(unsigned n, bool v) {
|
||||
std::vector<bool> b(n, !v);
|
||||
mp11::mp_for_each<Ns>(bool_mask_op{b, v});
|
||||
mp11::mp_for_each<mp11::mp_list<Ns...>>(bool_mask_impl{b, v});
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Axes, typename Ns> struct axes_assign_subset_op {
|
||||
const Axes &axes_;
|
||||
template <int N, typename R>
|
||||
auto operator()(mp11::mp_int<N>, R &r) const -> mp11::mp_int<N + 1> {
|
||||
using I2 = typename mp11::mp_at_c<Ns, N>::type;
|
||||
r = std::get<I2::value>(axes_);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ns, typename Axes1, typename Axes>
|
||||
void axes_assign_subset(Axes1 &axes1, const Axes &axes) {
|
||||
// fusion::fold(axes1, mpl::int_<0>(), axes_assign_subset_op<Axes, Ns>{axes});
|
||||
}
|
||||
|
||||
template <typename Ns>
|
||||
using unique_sorted_t = mp11::mp_unique<mp11::mp_sort<Ns, mp11::mp_less>>;
|
||||
|
||||
template <typename Axes, typename Numbers>
|
||||
struct axes_select {
|
||||
template <typename I>
|
||||
using axes_at = mp11::mp_at<Axes, I>;
|
||||
using type = mp11::mp_transform<axes_at, Numbers>;
|
||||
};
|
||||
|
||||
template <typename Axes, typename Numbers>
|
||||
using axes_select_t = typename axes_select<Axes, Numbers>::type;
|
||||
|
||||
template <typename T>
|
||||
using size_of = std::tuple_size<typename std::decay<T>::type>;
|
||||
|
||||
@@ -121,25 +100,43 @@ template <unsigned D, typename T>
|
||||
using type_of = typename std::tuple_element<D, typename std::decay<T>::type>::type;
|
||||
|
||||
namespace {
|
||||
template <typename Tuple, typename F>
|
||||
struct for_each_fn {
|
||||
Tuple&& t;
|
||||
F&& f;
|
||||
for_each_fn(Tuple&& tt, F&& ff) :
|
||||
t(std::forward<Tuple>(tt)), f(std::forward<F>(ff)) {}
|
||||
template <typename Int> void operator()(Int) const {
|
||||
f(std::get<Int::value>(t));
|
||||
template <typename L, typename... Ns>
|
||||
struct selection_impl {
|
||||
template <typename Int> using at = mp11::mp_at<L, Int>;
|
||||
using N = mp11::mp_list<Ns...>;
|
||||
using LNs = mp11::mp_assign<L, N>;
|
||||
using type = mp11::mp_transform<at, LNs>;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename L, typename... Ns>
|
||||
using selection = typename selection_impl<L, Ns...>::type;
|
||||
|
||||
template <typename Ns>
|
||||
using unique_sorted = mp11::mp_unique<mp11::mp_sort<Ns, mp11::mp_less>>;
|
||||
|
||||
namespace {
|
||||
template <typename Src, typename Dst>
|
||||
struct sub_tuple_assign_impl {
|
||||
const Src& src;
|
||||
Dst& dst;
|
||||
template <typename I1, typename I2>
|
||||
void operator()(std::pair<I1, I2>) const {
|
||||
std::get<I1::value>(dst) = std::get<I2::value>(src);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Tuple, typename F>
|
||||
void for_each(Tuple&& t, F&& f) {
|
||||
auto fn = for_each_fn<Tuple, F>(std::forward<Tuple>(t),
|
||||
std::forward<F>(f));
|
||||
using size = mp11::mp_size<typename std::decay<Tuple>::type>;
|
||||
using nums = mp11::mp_iota<size>;
|
||||
mp11::mp_for_each<nums>(fn);
|
||||
template <typename T, typename... Ns>
|
||||
selection<T, Ns...> make_sub_tuple(const T& t) {
|
||||
using U = selection<T, Ns...>;
|
||||
U u;
|
||||
using N1 = mp11::mp_list<Ns...>;
|
||||
using Len = mp11::mp_size<N1>;
|
||||
using N2 = mp11::mp_iota<Len>;
|
||||
using N3 = mp11::mp_transform<std::pair, N2, N1>;
|
||||
mp11::mp_for_each<N3>(sub_tuple_assign_impl<T, U>{t, u});
|
||||
return u;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -53,7 +53,7 @@ class histogram<dynamic_tag, Axes, Storage> {
|
||||
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
|
||||
|
||||
public:
|
||||
using any_axis_type = axis::any<Axes>;
|
||||
using any_axis_type = mp11::mp_rename<Axes, axis::any>;
|
||||
using axes_type = std::vector<any_axis_type>;
|
||||
using element_type = typename Storage::element_type;
|
||||
using const_reference = typename Storage::const_reference;
|
||||
@@ -67,8 +67,9 @@ public:
|
||||
histogram &operator=(const histogram &) = default;
|
||||
histogram &operator=(histogram &&) = default;
|
||||
|
||||
template <typename... Axes1>
|
||||
explicit histogram(const Axes1 &... axes) : axes_({any_axis_type(axes)...}) {
|
||||
template <typename... Axis>
|
||||
explicit histogram(Axis &&... axis) :
|
||||
axes_({any_axis_type(std::forward<Axis>(axis))...}) {
|
||||
storage_ = Storage(bincount_from_axes());
|
||||
}
|
||||
|
||||
@@ -93,11 +94,11 @@ public:
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
explicit histogram(histogram<dynamic_tag, Axes, S> &&rhs)
|
||||
explicit histogram(dynamic_histogram<Axes, S> &&rhs)
|
||||
: axes_(std::move(rhs.axes_)), storage_(std::move(rhs.storage_)) {}
|
||||
|
||||
template <typename S>
|
||||
histogram &operator=(histogram<dynamic_tag, Axes, S> &&rhs) {
|
||||
histogram &operator=(dynamic_histogram<Axes, S> &&rhs) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
|
||||
axes_ = std::move(rhs.axes_);
|
||||
storage_ = std::move(rhs.storage_);
|
||||
@@ -466,65 +467,85 @@ private:
|
||||
template <typename Archive> void serialize(Archive &, unsigned);
|
||||
};
|
||||
|
||||
template <typename... Axes>
|
||||
histogram<dynamic_tag, detail::union_t<axis::builtins, mp11::mp_list<Axes...>>>
|
||||
make_dynamic_histogram(Axes &&... axes) {
|
||||
return histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, mp11::mp_list<Axes...>>>(
|
||||
std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
template <typename... Axes>
|
||||
histogram<dynamic_tag, detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
array_storage<weight_counter<double>>>
|
||||
make_dynamic_weighted_histogram(Axes &&... axes) {
|
||||
return histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
array_storage<weight_counter<double>>>(
|
||||
std::forward<Axes>(axes)...);
|
||||
template <typename... Axis>
|
||||
dynamic_histogram<
|
||||
mp11::mp_set_push_back<axis::builtins, Axis...>
|
||||
>
|
||||
make_dynamic_histogram(Axis &&... axis) {
|
||||
using H = dynamic_histogram<
|
||||
mp11::mp_set_push_back<axis::builtins, Axis...>
|
||||
>;
|
||||
return H(std::forward<Axis>(axis)...);
|
||||
}
|
||||
|
||||
template <typename Storage, typename... Axes>
|
||||
histogram<dynamic_tag, detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
Storage>
|
||||
dynamic_histogram<
|
||||
mp11::mp_set_push_back<axis::builtins, Axes...>,
|
||||
Storage
|
||||
>
|
||||
make_dynamic_histogram_with(Axes &&... axes) {
|
||||
return histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
Storage>(std::forward<Axes>(axes)...);
|
||||
using H = dynamic_histogram<
|
||||
mp11::mp_set_push_back<axis::builtins, Axes...>,
|
||||
Storage
|
||||
>;
|
||||
return H(std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>>
|
||||
dynamic_histogram<
|
||||
mp11::mp_unique<
|
||||
mp11::mp_append<
|
||||
axis::builtins,
|
||||
typename Iterator::value_type::types
|
||||
>
|
||||
>
|
||||
>
|
||||
make_dynamic_histogram(Iterator begin, Iterator end) {
|
||||
return histogram<
|
||||
dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>>(
|
||||
begin, end);
|
||||
using H = dynamic_histogram<
|
||||
mp11::mp_unique<
|
||||
mp11::mp_append<
|
||||
axis::builtins,
|
||||
typename Iterator::value_type::types
|
||||
>
|
||||
>
|
||||
>;
|
||||
return H(begin, end);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
array_storage<weight_counter<double>>>
|
||||
make_dynamic_weighted_histogram(Iterator begin, Iterator end) {
|
||||
return histogram<
|
||||
dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
array_storage<weight_counter<double>>>(begin, end);
|
||||
}
|
||||
// template <typename... Axes>
|
||||
// dynamic_histogram<
|
||||
|
||||
// detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
// array_storage<weight_counter<double>>>
|
||||
// make_dynamic_weighted_histogram(Axes &&... axes) {
|
||||
// return dynamic_histogram,
|
||||
// detail::union_t<axis::builtins, mp11::mp_list<Axes...>>,
|
||||
// array_storage<weight_counter<double>>>(
|
||||
// std::forward<Axes>(axes)...);
|
||||
// }
|
||||
|
||||
template <typename Storage, typename Iterator,
|
||||
typename = detail::requires_iterator<Iterator>>
|
||||
histogram<dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
Storage>
|
||||
make_dynamic_histogram_with(Iterator begin, Iterator end) {
|
||||
return histogram<
|
||||
dynamic_tag,
|
||||
detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
Storage>(begin, end);
|
||||
}
|
||||
// template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
// dynamic_histogram,
|
||||
// detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
// array_storage<weight_counter<double>>>
|
||||
// make_dynamic_weighted_histogram(Iterator begin, Iterator end) {
|
||||
// return histogram<
|
||||
// dynamic_tag,
|
||||
// detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
// array_storage<weight_counter<double>>>(begin, end);
|
||||
// }
|
||||
|
||||
// template <typename Storage, typename Iterator,
|
||||
// typename = detail::requires_iterator<Iterator>>
|
||||
// dynamic_histogram,
|
||||
// detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
// Storage>
|
||||
// make_dynamic_histogram_with(Iterator begin, Iterator end) {
|
||||
// return histogram<
|
||||
// dynamic_tag,
|
||||
// detail::union_t<axis::builtins, typename Iterator::value_type::types>,
|
||||
// Storage>(begin, end);
|
||||
// }
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
@@ -34,8 +34,8 @@ template <int N, char First, char... Rest> constexpr int parse() {
|
||||
} // namespace detail
|
||||
|
||||
template <char... Digits>
|
||||
auto operator"" _c() -> mp11::mp_int<detail::parse<0, Digits...>()> {
|
||||
return {};
|
||||
auto operator"" _c() -> decltype(mpl::int_<detail::parse<0u, Digits...>()>()) {
|
||||
return ::boost::mp11::mp_int<detail::parse<0u, Digits...>()>();
|
||||
}
|
||||
|
||||
} // namespace literals
|
||||
|
||||
@@ -193,7 +193,7 @@ template <class Archive>
|
||||
void histogram<static_tag, A, S>::serialize(Archive &ar,
|
||||
unsigned /* version */) {
|
||||
detail::serialize_helper<Archive> sh(ar);
|
||||
detail::for_each(axes_, sh);
|
||||
mp11::tuple_for_each(axes_, sh);
|
||||
ar &storage_;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class histogram<static_tag, Axes, Storage> {
|
||||
static_assert(axes_size::value > 0, "at least one axis required");
|
||||
|
||||
public:
|
||||
using axes_type = mp11::mp_apply<std::tuple, Axes>;
|
||||
using axes_type = mp11::mp_rename<Axes, std::tuple>;
|
||||
using element_type = typename Storage::element_type;
|
||||
using const_reference = typename Storage::const_reference;
|
||||
using const_iterator = iterator_over<histogram, Storage>;
|
||||
@@ -50,8 +50,10 @@ public:
|
||||
histogram &operator=(const histogram &rhs) = default;
|
||||
histogram &operator=(histogram &&rhs) = default;
|
||||
|
||||
template <typename... Axis>
|
||||
explicit histogram(Axis &&... axis) : axes_(std::forward<Axis>(axis)...) {
|
||||
template <typename Axis0, typename ... Axis,
|
||||
typename = detail::requires_axis<Axis0>>
|
||||
explicit histogram(Axis0 && axis0, Axis &&... axis)
|
||||
: axes_(std::forward<Axis0>(axis0), std::forward<Axis>(axis)...) {
|
||||
storage_ = Storage(bincount_from_axes());
|
||||
}
|
||||
|
||||
@@ -60,11 +62,11 @@ public:
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
explicit histogram(const histogram<static_tag, Axes, S> &rhs)
|
||||
explicit histogram(const static_histogram<Axes, S> &rhs)
|
||||
: axes_(rhs.axes_), storage_(rhs.storage_) {}
|
||||
|
||||
template <typename S>
|
||||
histogram &operator=(const histogram<static_tag, Axes, S> &rhs) {
|
||||
histogram &operator=(const static_histogram<Axes, S> &rhs) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
|
||||
axes_ = rhs.axes_;
|
||||
storage_ = rhs.storage_;
|
||||
@@ -73,13 +75,13 @@ public:
|
||||
}
|
||||
|
||||
template <typename A, typename S>
|
||||
explicit histogram(const histogram<dynamic_tag, A, S> &rhs)
|
||||
explicit histogram(const dynamic_histogram<A, S> &rhs)
|
||||
: storage_(rhs.storage_) {
|
||||
detail::axes_assign(axes_, rhs.axes_);
|
||||
}
|
||||
|
||||
template <typename A, typename S>
|
||||
histogram &operator=(const histogram<dynamic_tag, A, S> &rhs) {
|
||||
histogram &operator=(const dynamic_histogram<A, S> &rhs) {
|
||||
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
|
||||
detail::axes_assign(axes_, rhs.axes_);
|
||||
storage_ = rhs.storage_;
|
||||
@@ -88,36 +90,35 @@ public:
|
||||
}
|
||||
|
||||
template <typename A, typename S>
|
||||
bool operator==(const histogram<static_tag, A, S> &) const noexcept {
|
||||
bool operator==(const static_histogram<A, S> &) const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
bool operator==(const histogram<static_tag, Axes, S> &rhs) const noexcept {
|
||||
bool operator==(const static_histogram<Axes, S> &rhs) const noexcept {
|
||||
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
|
||||
}
|
||||
|
||||
template <typename A, typename S>
|
||||
bool operator==(const histogram<dynamic_tag, A, S> &rhs) const noexcept {
|
||||
bool operator==(const dynamic_histogram<A, S> &rhs) const noexcept {
|
||||
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
bool operator!=(const histogram<Ts...> &rhs) const noexcept {
|
||||
template <typename T, typename A, typename S>
|
||||
bool operator!=(const histogram<T, A, S> &rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
histogram &operator+=(const histogram<static_tag, Axes, S> &rhs) {
|
||||
histogram &operator+=(const static_histogram<Axes, S> &rhs) {
|
||||
BOOST_ASSERT_MSG(detail::axes_equal(axes_, rhs.axes_), "axes of histograms differ");
|
||||
storage_ += rhs.storage_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename A, typename S>
|
||||
histogram &operator+=(const histogram<dynamic_tag, A, S> &rhs) {
|
||||
if (!detail::axes_equal(axes_, rhs.axes_))
|
||||
throw std::invalid_argument("axes of histograms differ");
|
||||
histogram &operator+=(const dynamic_histogram<A, S> &rhs) {
|
||||
BOOST_ASSERT_MSG(detail::axes_equal(axes_, rhs.axes_), "axes of histograms differ");
|
||||
storage_ += rhs.storage_;
|
||||
return *this;
|
||||
}
|
||||
@@ -149,6 +150,7 @@ public:
|
||||
detail::classify_container_t<T>>(), std::forward<T>(t));
|
||||
}
|
||||
|
||||
// TODO: merge this with unpacking
|
||||
template <typename W, typename... Ts> void operator()(detail::weight<W>&& w,
|
||||
Ts &&... ts) {
|
||||
// case with one argument is ambiguous, is specialized below
|
||||
@@ -158,6 +160,7 @@ public:
|
||||
fill_storage_impl(idx, std::move(w));
|
||||
}
|
||||
|
||||
// TODO: remove as obsolete
|
||||
template <typename W, typename T> void operator()(detail::weight<W>&& w,
|
||||
T&&t) {
|
||||
// check whether we need to unpack argument
|
||||
@@ -166,13 +169,13 @@ public:
|
||||
detail::classify_container_t<T>>(), std::forward<T>(t), std::move(w));
|
||||
}
|
||||
|
||||
template <typename... Indices>
|
||||
const_reference at(Indices &&... indices) const {
|
||||
template <typename... Ts>
|
||||
const_reference at(Ts &&... ts) const {
|
||||
// case with one argument is ambiguous, is specialized below
|
||||
static_assert(sizeof...(indices) == axes_size::value,
|
||||
static_assert(sizeof...(ts) == axes_size::value,
|
||||
"bin arguments do not match histogram dimension");
|
||||
std::size_t idx = 0, stride = 1;
|
||||
lin<0>(idx, stride, static_cast<int>(indices)...);
|
||||
lin<0>(idx, stride, static_cast<int>(ts)...);
|
||||
if (stride == 0)
|
||||
throw std::out_of_range("bin index out of range");
|
||||
return storage_[idx];
|
||||
@@ -232,24 +235,21 @@ public:
|
||||
|
||||
/// Apply unary functor/function to each axis
|
||||
template <typename Unary> void for_each_axis(Unary &&unary) const {
|
||||
detail::for_each(axes_, std::forward<Unary>(unary));
|
||||
mp11::tuple_for_each(axes_, std::forward<Unary>(unary));
|
||||
}
|
||||
|
||||
/// Returns a lower-dimensional histogram
|
||||
template <int N, typename... Rest>
|
||||
auto reduce_to(mp11::mp_int<N>, Rest...) const -> histogram<
|
||||
static_tag,
|
||||
detail::axes_select_t<Axes, mp11::mp_int<N>, Rest...>,
|
||||
template <int N, typename... Ns>
|
||||
auto reduce_to(mp11::mp_int<N>, Ns...) const -> static_histogram<
|
||||
detail::selection<Axes, mp11::mp_int<N>, Ns...>,
|
||||
Storage> {
|
||||
using HR = histogram<
|
||||
static_tag,
|
||||
detail::axes_select_t<Axes, mp11::mp_int<N>, Rest...>,
|
||||
Storage>;
|
||||
typename HR::axes_type axes;
|
||||
detail::axes_assign_subset<mp11::mp_int<N>, Rest...>(axes, axes_);
|
||||
auto hr = HR(std::move(axes));
|
||||
using HR = static_histogram<
|
||||
detail::selection<Axes, mp11::mp_int<N>, Ns...>,
|
||||
Storage
|
||||
>;
|
||||
auto hr = HR(detail::make_sub_axes<axes_type, mp11::mp_int<N>, Ns...>(axes_));
|
||||
const auto b =
|
||||
detail::bool_mask<mp11::mp_size_t<N>, Rest...>(dim(), true);
|
||||
detail::bool_mask<mp11::mp_int<N>, Ns...>(dim(), true);
|
||||
reduce_impl(hr, b);
|
||||
return hr;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ private:
|
||||
|
||||
std::size_t bincount_from_axes() const noexcept {
|
||||
detail::field_count_visitor fc;
|
||||
detail::for_each(axes_, fc);
|
||||
mp11::tuple_for_each(axes_, fc);
|
||||
return fc.value;
|
||||
}
|
||||
|
||||
@@ -450,27 +450,27 @@ private:
|
||||
|
||||
/// default static type factory
|
||||
template <typename... Axis>
|
||||
inline histogram<static_tag, mp11::mp_list<Axis...>>
|
||||
static_histogram<mp11::mp_list<Axis...>>
|
||||
make_static_histogram(Axis &&... axis) {
|
||||
using h = histogram<static_tag, mp11::mp_list<Axis...>>;
|
||||
return h(typename h::axes_type(std::forward<Axis>(axis)...));
|
||||
}
|
||||
|
||||
template <typename... Axis>
|
||||
inline histogram<static_tag, mp11::mp_list<Axis...>,
|
||||
array_storage<weight_counter<double>>>
|
||||
make_static_weighted_histogram(Axis &&... axis) {
|
||||
using h = histogram<static_tag, mp11::mp_list<Axis...>,
|
||||
array_storage<weight_counter<double>>>;
|
||||
return h(typename h::axes_type(std::forward<Axis>(axis)...));
|
||||
using H = static_histogram<mp11::mp_list<Axis...>>;
|
||||
return H(std::forward<Axis>(axis)...);
|
||||
}
|
||||
|
||||
/// static type factory with variable storage type
|
||||
template <typename Storage, typename... Axis>
|
||||
inline histogram<static_tag, mp11::mp_list<Axis...>, Storage>
|
||||
static_histogram<mp11::mp_list<Axis...>, Storage>
|
||||
make_static_histogram_with(Axis &&... axis) {
|
||||
using h = histogram<static_tag, mp11::mp_list<Axis...>, Storage>;
|
||||
return h(typename h::axes_type(std::forward<Axis>(axis)...));
|
||||
using H = static_histogram<mp11::mp_list<Axis...>, Storage>;
|
||||
return H(std::forward<Axis>(axis)...);
|
||||
}
|
||||
|
||||
template <typename... Axis>
|
||||
static_histogram<mp11::mp_list<Axis...>,
|
||||
array_storage<weight_counter<double>>>
|
||||
make_static_weighted_histogram(Axis &&... axis) {
|
||||
using H = static_histogram<mp11::mp_list<Axis...>,
|
||||
array_storage<weight_counter<double>>>;
|
||||
return H(std::forward<Axis>(axis)...);
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
|
||||
@@ -20,26 +20,38 @@
|
||||
#include <utility>
|
||||
|
||||
using namespace boost::histogram::detail;
|
||||
namespace mp11 = boost::mp11;
|
||||
|
||||
struct for_each_test_visitor {
|
||||
int i = 0;
|
||||
bool result = true;
|
||||
template <typename T> void operator()(T& t) {
|
||||
// expect: int char float
|
||||
switch (i++) {
|
||||
case 0:
|
||||
result &= std::is_same<T, int>::value;
|
||||
break;
|
||||
case 1:
|
||||
result &= std::is_same<T, char>::value;
|
||||
break;
|
||||
case 2:
|
||||
result &= std::is_same<T, float>::value;
|
||||
};
|
||||
t += 1;
|
||||
using i0 = mp11::mp_int<0>;
|
||||
using i1 = mp11::mp_int<1>;
|
||||
using i2 = mp11::mp_int<2>;
|
||||
using i3 = mp11::mp_int<3>;
|
||||
|
||||
namespace boost { namespace detail {
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
|
||||
os << "[";
|
||||
for (const auto& x : v)
|
||||
os << x << " ";
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct ostreamer {
|
||||
std::ostream& os;
|
||||
template <typename T> void operator()(const T& t) const {
|
||||
os << t << " ";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t) {
|
||||
os << "[";
|
||||
mp11::tuple_for_each(t, ostreamer{os});
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
}}
|
||||
|
||||
int main() {
|
||||
// escape0
|
||||
@@ -113,25 +125,9 @@ int main() {
|
||||
}
|
||||
|
||||
// cat
|
||||
{ BOOST_TEST_EQ(cat("foo", 1, "bar"), std::string("foo1bar")); }
|
||||
|
||||
// unique_sorted
|
||||
{
|
||||
using input = ::boost::mp11::mp_list_c<int, 3, 2, 1, 2, 3, 1, 3>;
|
||||
using result = unique_sorted_t<input>;
|
||||
using expected = ::boost::mp11::mp_list_c<int, 1, 2, 3>;
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<result, expected>));
|
||||
}
|
||||
|
||||
// union
|
||||
{
|
||||
using main_list = ::boost::mp11::mp_list<int, unsigned, char>;
|
||||
using aux_list = ::boost::mp11::mp_list<unsigned, void *>;
|
||||
using result = union_t<main_list, aux_list>;
|
||||
using expected = ::boost::mp11::mp_list<int, unsigned, char, void *>;
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<result, expected>));
|
||||
BOOST_TEST_EQ(cat("foo", 1, "bar"),
|
||||
std::string("foo1bar"));
|
||||
}
|
||||
|
||||
// has_variance_support
|
||||
@@ -183,16 +179,50 @@ int main() {
|
||||
BOOST_TEST_TRAIT_TRUE(( std::is_same<result4, dynamic_container_tag> ));
|
||||
}
|
||||
|
||||
// for_each
|
||||
// bool mask
|
||||
{
|
||||
for_each_test_visitor v;
|
||||
std::tuple<int, char, float> t(0, 0, 0);
|
||||
::boost::histogram::detail::for_each(t, v);
|
||||
BOOST_TEST_EQ(v.i, 3);
|
||||
BOOST_TEST_EQ(v.result, true);
|
||||
BOOST_TEST_EQ(std::get<0>(t), 1);
|
||||
BOOST_TEST_EQ(std::get<1>(t), 1);
|
||||
BOOST_TEST_EQ(std::get<2>(t), 1);
|
||||
auto v1 = bool_mask<i1, i2>(4, false);
|
||||
BOOST_TEST_EQ(v1, std::vector<bool>({true, false, false, true}));
|
||||
|
||||
auto v2 = bool_mask<i1, i3>(4, true);
|
||||
BOOST_TEST_EQ(v2, std::vector<bool>({false, true, false, true}));
|
||||
}
|
||||
|
||||
// // literals
|
||||
// {
|
||||
// using c0 = 0_c;
|
||||
// BOOST_TEST_TRAIT_TRUE((std::is_same<c0, mp11::mp_int<0>>));
|
||||
// }
|
||||
|
||||
// selection
|
||||
{
|
||||
struct A {};
|
||||
struct B {};
|
||||
struct C {};
|
||||
|
||||
using input = mp11::mp_list<A, B, C>;
|
||||
using result = selection<input, i2, i0>;
|
||||
using expected = mp11::mp_list<C, A>;
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<result, expected>));
|
||||
}
|
||||
|
||||
// unique_sorted
|
||||
{
|
||||
using input = mp11::mp_list_c<int, 3, 3, 1, 2, 1, 2>;
|
||||
using result = unique_sorted<input>;
|
||||
using expected = mp11::mp_list_c<int, 1, 2, 3>;
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<result, expected>));
|
||||
}
|
||||
|
||||
// make_sub_tuple
|
||||
{
|
||||
std::tuple<int, long, char> t(1, 2, 3);
|
||||
auto result = make_sub_tuple<decltype(t), i1, i2>(t);
|
||||
auto expected = std::tuple<long, char>(2, 3);
|
||||
|
||||
BOOST_TEST_EQ(result, expected);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
Reference in New Issue
Block a user