refactoring

This commit is contained in:
Hans Dembinski
2017-11-13 10:54:23 +01:00
parent 210414434a
commit c5094149de
20 changed files with 571 additions and 446 deletions

View File

@@ -7,7 +7,7 @@
#ifndef BOOST_HISTOGRAM_HPP_
#define BOOST_HISTOGRAM_HPP_
#include <boost/histogram/axis.hpp>
#include <boost/histogram/axis/axis.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/histogram/storage/adaptive_storage.hpp>

View File

@@ -0,0 +1,96 @@
// Copyright 2015-2016 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_ARITHMETIC_OPERATORS_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_ARITHMETIC_OPERATORS_HPP_
#include <boost/histogram/histogram_fwd.hpp>
namespace boost {
namespace histogram {
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator+(H<A, S> &&a,
const H<A, S> &b) {
a += b;
return std::move(a);
}
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator+(H<A, S> &&a,
H<A, S> &&b) {
a += b;
return std::move(a);
}
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator+(const H<A, S> &a,
H<A, S> &&b) {
b += a;
return std::move(b);
}
template <template <class, class> class H, typename A, typename S>
H<A, S>
operator+(const H<A, S> &a,
const H<A, S> &b) {
H<A, S> r(a);
r += b;
return r;
}
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator*(H<A, S> &&a, const double x) {
a *= x;
return std::move(a);
}
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator*(const double x, H<A, S> &&b) {
b *= x;
return std::move(b);
}
template <template <class, class> class H, typename A, typename S>
H<A, S>
operator*(const H<A, S> &a, const double x) {
H<A, S> r(a);
r *= x;
return r;
}
template <template <class, class> class H, typename A, typename S>
H<A, S>
operator*(const double x, const H<A, S> &b) {
H<A, S> r(b);
r *= x;
return r;
}
template <template <class, class> class H, typename A, typename S>
H<A, S> &&
operator/(H<A, S> &&a, const double x) {
a /= x;
return std::move(a);
}
template <template <class, class> class H, typename A, typename S>
H<A, S>
operator/(const H<A, S> &a, const double x) {
H<A, S> r(a);
r /= x;
return r;
}
} // namespace histogram
} // namespace boost
#endif

View File

@@ -0,0 +1,196 @@
// Copyright 2015-2016 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_AXIS_ANY_HPP_
#define _BOOST_HISTOGRAM_AXIS_ANY_HPP_
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/interval.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/histogram/detail/axis_visitor.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/variant.hpp>
#include <stdexcept>
#include <type_traits>
#include <utility>
// forward declaration for serialization
namespace boost {
namespace serialization {
class access;
} // namespace serialization
} // namespace boost
namespace boost {
namespace histogram {
namespace axis {
namespace detail {
struct size : public static_visitor<int> {
template <typename A> int operator()(const A &a) const { return a.size(); }
};
struct shape : public static_visitor<int> {
template <typename A> int operator()(const A &a) const { return a.shape(); }
};
struct uoflow : public static_visitor<bool> {
template <typename A> bool operator()(const A &a) const { return a.uoflow(); }
};
struct get_label : public static_visitor<string_view> {
template <typename A> ::boost::string_view operator()(const A& a) const { return a.label(); }
};
struct set_label : public static_visitor<void> {
const ::boost::string_view label;
set_label(const ::boost::string_view x) : label(x) {}
template <typename A> void operator()(A& a) const { a.label(label); }
};
template <typename T> struct index : public static_visitor<int> {
const T &t;
explicit index(const T &arg) : t(arg) {}
template <typename Axis> int operator()(const Axis &a) const {
return impl(std::is_convertible<T, typename Axis::value_type>(), a);
}
template <typename Axis> int impl(std::true_type, const Axis& a) const {
return a.index(t);
}
template <typename Axis> int impl(std::false_type, const Axis&) const {
throw std::runtime_error("index argument not convertible to axis value type");
}
};
struct bin : public static_visitor<axis::interval<double>> {
using double_interval = axis::interval<double>;
const int i;
bin(const int v) : i(v) {}
template <typename A> double_interval operator()(const A &a) const {
return impl(is_convertible<typename A::bin_type, double_interval>(),
std::forward<typename A::bin_type>(a[i]));
}
template <typename B> double_interval impl(true_type, B &&b) const {
return b;
}
template <typename B> double_interval impl(false_type, B &&) const {
throw std::runtime_error("cannot convert bin_type to interval<double>");
}
};
} // namespace detail
/// Polymorphic axis type
template <typename Axes>
class any : public make_variant_over<Axes>::type {
using base_type = typename make_variant_over<Axes>::type;
public:
using types = typename base_type::types;
using value_type = double;
using bin_type = interval<double>;
using const_iterator = axis_iterator<any>;
any() = default;
any(const any& t) = default;
any(any&& t) = default;
any& operator=(const any& t) = default;
any& operator=(any&& t) = default;
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any(const T& t) : base_type(t) {}
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any& operator=(const T& t) {
// ugly workaround for compiler bug
return reinterpret_cast<any&>(base_type::operator=(t));
}
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any& operator=(T&& t) {
// ugly workaround for compiler bug
return reinterpret_cast<any&>(base_type::operator=(std::move(t)));
}
int size() const {
return apply_visitor(detail::size(), *this);
}
int shape() const {
return apply_visitor(detail::shape(), *this);
}
bool uoflow() const {
return apply_visitor(detail::uoflow(), *this);
}
// note: this only works for axes with compatible value type
int index(const value_type x) const {
return apply_visitor(detail::index<value_type>(x), *this);
}
string_view label() const {
return apply_visitor(detail::get_label(), *this);
}
void label(const string_view x) {
return apply_visitor(detail::set_label(x), *this);
}
// this only works for axes with compatible bin type
// and will raise an error otherwise
bin_type operator[](const int i) const {
return apply_visitor(detail::bin(i), *this);
}
bool operator==(const any& rhs) const {
return base_type::operator==(static_cast<const base_type&>(rhs));
}
const_iterator begin() const { return const_iterator(*this, 0); }
const_iterator end() const { return const_iterator(*this, size()); }
private:
friend class ::boost::serialization::access;
template <typename Archive> void serialize(Archive&, unsigned);
};
// dynamic casts
template <typename T, typename Axes>
typename std::add_lvalue_reference<T>::type cast(any<Axes>& any) { return get<T>(any); }
template <typename T, typename Axes>
const typename std::add_lvalue_reference<T>::type cast(const any<Axes>& any) { return get<T>(any); }
template <typename T, typename Axes>
typename std::add_pointer<T>::type cast(any<Axes>* any) { return get<T>(&any); }
template <typename T, typename Axes>
const typename std::add_pointer<T>::type cast(const any<Axes>* any) { return get<T>(&any); }
// pass-through versions for generic programming, i.e. when you switch to static histogram
template <typename T>
typename std::add_lvalue_reference<T>::type cast(T& t) { return t; }
template <typename T>
const typename std::add_lvalue_reference<T>::type cast(const T& t) { return t; }
template <typename T>
typename std::add_pointer<T>::type cast(T* t) { return t; }
template <typename T>
const typename std::add_pointer<T>::type cast(const T* t) { return t; }
} // namespace axis
} // namespace histogram
} // namespace boost
#endif

View File

@@ -9,14 +9,10 @@
#include <algorithm>
#include <boost/bimap.hpp>
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/interval.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/histogram/detail/axis_visitor.hpp>
#include <boost/mpl/contains.hpp>
#include <cmath>
#include <limits>
#include <memory>
@@ -25,7 +21,6 @@
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
// forward declaration for serialization
namespace boost {
@@ -36,41 +31,10 @@ class access;
namespace boost {
namespace histogram {
namespace axis {
enum class uoflow { off = false, on = true };
template <typename Axis>
class axis_iterator
: public iterator_facade<axis_iterator<Axis>,
std::pair<int, typename Axis::bin_type>,
random_access_traversal_tag,
std::pair<int, typename Axis::bin_type>> {
public:
explicit axis_iterator(const Axis &axis, int idx) : axis_(axis), idx_(idx) {}
axis_iterator(const axis_iterator &o) = default;
axis_iterator &operator=(const axis_iterator &o) = default;
private:
void increment() noexcept { ++idx_; }
void decrement() noexcept { --idx_; }
void advance(int n) noexcept { idx_ += n; }
int distance_to(const axis_iterator &other) const noexcept {
return other.idx_ - idx_;
}
bool equal(const axis_iterator &other) const noexcept {
return idx_ == other.idx_;
}
std::pair<int, typename Axis::bin_type> dereference() const {
return std::make_pair(idx_, axis_[idx_]);
}
const Axis& axis_;
int idx_;
friend class boost::iterator_core_access;
};
/// Base class for all axes.
class axis_base {
public:
@@ -591,168 +555,6 @@ private:
friend class ::boost::serialization::access;
template <class Archive> void serialize(Archive &, unsigned);
};
namespace detail {
struct size : public static_visitor<int> {
template <typename A> int operator()(const A &a) const { return a.size(); }
};
struct shape : public static_visitor<int> {
template <typename A> int operator()(const A &a) const { return a.shape(); }
};
struct uoflow : public static_visitor<bool> {
template <typename A> bool operator()(const A &a) const { return a.uoflow(); }
};
struct get_label : public static_visitor<string_view> {
template <typename A> ::boost::string_view operator()(const A& a) const { return a.label(); }
};
struct set_label : public static_visitor<void> {
const ::boost::string_view label;
set_label(const ::boost::string_view x) : label(x) {}
template <typename A> void operator()(A& a) const { a.label(label); }
};
template <typename T> struct index : public static_visitor<int> {
const T &t;
explicit index(const T &arg) : t(arg) {}
template <typename Axis> int operator()(const Axis &a) const {
return impl(std::is_convertible<T, typename Axis::value_type>(), a);
}
template <typename Axis> int impl(std::true_type, const Axis& a) const {
return a.index(t);
}
template <typename Axis> int impl(std::false_type, const Axis&) const {
throw std::runtime_error("index argument not convertible to axis value type");
}
};
struct bin : public static_visitor<axis::interval<double>> {
using double_interval = axis::interval<double>;
const int i;
bin(const int v) : i(v) {}
template <typename A> double_interval operator()(const A &a) const {
return impl(is_convertible<typename A::bin_type, double_interval>(),
std::forward<typename A::bin_type>(a[i]));
}
template <typename B> double_interval impl(true_type, B &&b) const {
return b;
}
template <typename B> double_interval impl(false_type, B &&) const {
throw std::runtime_error("cannot convert bin_type to interval<double>");
}
};
} // namespace detail
/// Polymorphic axis type
template <typename Axes = builtins>
class any : public make_variant_over<Axes>::type {
using base_type = typename make_variant_over<Axes>::type;
public:
using types = typename base_type::types;
using value_type = double;
using bin_type = interval<double>;
using const_iterator = axis_iterator<any>;
any() = default;
any(const any& t) = default;
any(any&& t) = default;
any& operator=(const any& t) = default;
any& operator=(any&& t) = default;
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any(const T& t) : base_type(t) {}
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any& operator=(const T& t) {
// ugly workaround for compiler bug
return reinterpret_cast<any&>(base_type::operator=(t));
}
template <typename T, typename = typename std::enable_if<
mpl::contains<Axes, T>::value
>::type>
any& operator=(T&& t) {
// ugly workaround for compiler bug
return reinterpret_cast<any&>(base_type::operator=(std::move(t)));
}
int size() const {
return apply_visitor(detail::size(), *this);
}
int shape() const {
return apply_visitor(detail::shape(), *this);
}
bool uoflow() const {
return apply_visitor(detail::uoflow(), *this);
}
// note: this only works for axes with compatible value type
int index(const value_type x) const {
return apply_visitor(detail::index<value_type>(x), *this);
}
string_view label() const {
return apply_visitor(detail::get_label(), *this);
}
void label(const string_view x) {
return apply_visitor(detail::set_label(x), *this);
}
// this only works for axes with compatible bin type
// and will raise an error otherwise
bin_type operator[](const int i) const {
return apply_visitor(detail::bin(i), *this);
}
bool operator==(const any& rhs) const {
return base_type::operator==(static_cast<const base_type&>(rhs));
}
const_iterator begin() const { return const_iterator(*this, 0); }
const_iterator end() const { return const_iterator(*this, size()); }
private:
friend class ::boost::serialization::access;
template <typename Archive> void serialize(Archive&, unsigned);
};
// dynamic casts
template <typename T, typename Axes>
typename std::add_lvalue_reference<T>::type cast(any<Axes>& any) { return get<T>(any); }
template <typename T, typename Axes>
const typename std::add_lvalue_reference<T>::type cast(const any<Axes>& any) { return get<T>(any); }
template <typename T, typename Axes>
typename std::add_pointer<T>::type cast(any<Axes>* any) { return get<T>(&any); }
template <typename T, typename Axes>
const typename std::add_pointer<T>::type cast(const any<Axes>* any) { return get<T>(&any); }
// pass-through versions for generic programming, i.e. when you switch to static histogram
template <typename T>
typename std::add_lvalue_reference<T>::type cast(T& t) { return t; }
template <typename T>
const typename std::add_lvalue_reference<T>::type cast(const T& t) { return t; }
template <typename T>
typename std::add_pointer<T>::type cast(T* t) { return t; }
template <typename T>
const typename std::add_pointer<T>::type cast(const T* t) { return t; }
} // namespace axis
} // namespace histogram
} // namespace boost

View File

@@ -0,0 +1,47 @@
// Copyright 2015-2016 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_AXIS_ITERATOR_HPP_
#define _BOOST_HISTOGRAM_AXIS_ITERATOR_HPP_
#include <boost/iterator/iterator_facade.hpp>
#include <utility>
namespace boost { namespace histogram { namespace axis {
template <typename Axis>
class axis_iterator
: public iterator_facade<axis_iterator<Axis>,
std::pair<int, typename Axis::bin_type>,
random_access_traversal_tag,
std::pair<int, typename Axis::bin_type>> {
public:
explicit axis_iterator(const Axis &axis, int idx) : axis_(axis), idx_(idx) {}
axis_iterator(const axis_iterator &o) = default;
axis_iterator &operator=(const axis_iterator &o) = default;
private:
void increment() noexcept { ++idx_; }
void decrement() noexcept { --idx_; }
void advance(int n) noexcept { idx_ += n; }
int distance_to(const axis_iterator &other) const noexcept {
return other.idx_ - idx_;
}
bool equal(const axis_iterator &other) const noexcept {
return idx_ == other.idx_;
}
std::pair<int, typename Axis::bin_type> dereference() const {
return std::make_pair(idx_, axis_[idx_]);
}
const Axis& axis_;
int idx_;
friend class boost::iterator_core_access;
};
}}}
#endif

View File

@@ -9,7 +9,7 @@
#ifndef _BOOST_HISTOGRAM_AXIS_OSTREAM_OPERATORS_HPP_
#define _BOOST_HISTOGRAM_AXIS_OSTREAM_OPERATORS_HPP_
#include <boost/histogram/axis.hpp>
#include <boost/histogram/axis/axis.hpp>
#include <boost/histogram/detail/utility.hpp>
#include <boost/histogram/interval.hpp>
#include <boost/math/constants/constants.hpp>

View File

@@ -9,7 +9,8 @@
#include <algorithm>
#include <boost/config.hpp>
#include <boost/histogram/axis.hpp>
#include <boost/histogram/axis/axis.hpp>
#include <boost/histogram/axis/any.hpp>
#include <boost/histogram/detail/axis_visitor.hpp>
#include <boost/histogram/detail/meta.hpp>
#include <boost/histogram/detail/utility.hpp>
@@ -43,7 +44,7 @@ namespace boost {
namespace histogram {
template <typename Axes, typename Storage>
class histogram<Dynamic, Axes, Storage> {
class dynamic_histogram {
static_assert(!mpl::empty<Axes>::value, "at least one axis required");
public:
using any_axis_type = axis::any<Axes>;
@@ -53,31 +54,45 @@ private:
using axes_type = std::vector<any_axis_type>;
public:
histogram() = default;
histogram(const histogram &) = default;
histogram(histogram &&) = default;
histogram &operator=(const histogram &) = default;
histogram &operator=(histogram &&) = default;
dynamic_histogram() = default;
dynamic_histogram(const dynamic_histogram &) = default;
dynamic_histogram(dynamic_histogram &&) = default;
dynamic_histogram &operator=(const dynamic_histogram &) = default;
dynamic_histogram &operator=(dynamic_histogram &&) = default;
template <typename... Axes1>
explicit histogram(const Axes1 &... axes) : axes_({any_axis_type(axes)...}) {
explicit dynamic_histogram(const Axes1 &... axes) : axes_({any_axis_type(axes)...}) {
storage_ = Storage(bincount_from_axes());
}
template <typename Iterator, typename = detail::is_iterator<Iterator>>
histogram(Iterator axes_begin, Iterator axes_end)
: axes_(std::distance(axes_begin, axes_end)) {
std::copy(axes_begin, axes_end, axes_.begin());
dynamic_histogram(Iterator begin, Iterator end)
: axes_(std::distance(begin, end)) {
std::copy(begin, end, axes_.begin());
storage_ = Storage(bincount_from_axes());
}
template <typename D, typename A, typename S>
explicit histogram(const histogram<D, A, S> &rhs) : storage_(rhs.storage_) {
template <typename A, typename S>
explicit dynamic_histogram(const static_histogram<A, S> &rhs) : storage_(rhs.storage_) {
detail::axes_assign(axes_, rhs.axes_);
}
template <typename D, typename A, typename S>
histogram &operator=(const histogram<D, A, S> &rhs) {
template <typename A, typename S>
explicit dynamic_histogram(const dynamic_histogram<A, S> &rhs) : storage_(rhs.storage_) {
detail::axes_assign(axes_, rhs.axes_);
}
template <typename A, typename S>
dynamic_histogram &operator=(const static_histogram<A, S> &rhs) {
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
detail::axes_assign(axes_, rhs.axes_);
storage_ = rhs.storage_;
}
return *this;
}
template <typename A, typename S>
dynamic_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_;
@@ -86,11 +101,11 @@ public:
}
template <typename S>
explicit histogram(histogram<Dynamic, Axes, S> &&rhs)
explicit dynamic_histogram(dynamic_histogram<Axes, S> &&rhs)
: axes_(std::move(rhs.axes_)), storage_(std::move(rhs.storage_)) {}
template <typename S>
histogram &operator=(histogram<Dynamic, Axes, S> &&rhs) {
dynamic_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_);
@@ -98,30 +113,48 @@ public:
return *this;
}
template <typename D, typename A, typename S>
bool operator==(const histogram<D, A, S> &rhs) const noexcept {
template <typename A, typename S>
bool operator==(const static_histogram<A, S> &rhs) const noexcept {
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
}
template <typename D, typename A, typename S>
bool operator!=(const histogram<D, A, S> &rhs) const noexcept {
template <typename A, typename S>
bool operator==(const dynamic_histogram<A, S> &rhs) const noexcept {
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
}
template <typename A, typename S>
bool operator!=(const static_histogram<A, S> &rhs) const noexcept {
return !operator==(rhs);
}
template <typename D, typename A, typename S>
histogram &operator+=(const histogram<D, A, S> &rhs) {
template <typename A, typename S>
bool operator!=(const dynamic_histogram<A, S> &rhs) const noexcept {
return !operator==(rhs);
}
template <typename A, typename S>
dynamic_histogram &operator+=(const static_histogram<A, S> &rhs) {
if (!detail::axes_equal(axes_, rhs.axes_))
throw std::logic_error("axes of histograms differ");
storage_ += rhs.storage_;
return *this;
}
histogram &operator*=(const value_type rhs) {
template <typename A, typename S>
dynamic_histogram &operator+=(const dynamic_histogram<A, S> &rhs) {
if (!detail::axes_equal(axes_, rhs.axes_))
throw std::logic_error("axes of histograms differ");
storage_ += rhs.storage_;
return *this;
}
dynamic_histogram &operator*=(const value_type rhs) {
storage_ *= rhs;
return *this;
}
histogram &operator/=(const value_type rhs) {
dynamic_histogram &operator/=(const value_type rhs) {
storage_ *= 1.0 / rhs;
return *this;
}
@@ -259,13 +292,13 @@ public:
}
/// Return a lower dimensional histogram
template <int N, typename... Rest> histogram reduce_to(mpl::int_<N>, Rest...) const {
template <int N, typename... Rest> dynamic_histogram reduce_to(mpl::int_<N>, Rest...) const {
const auto b = detail::bool_mask<mpl::vector<mpl::int_<N>, Rest...>>(dim(), true);
return reduce_impl(b);
}
/// Return a lower dimensional histogram
template <typename... Rest> histogram reduce_to(int n, Rest... rest) const {
template <typename... Rest> dynamic_histogram reduce_to(int n, Rest... rest) const {
std::vector<bool> b(dim(), false);
for (const auto &i : {n, rest...})
b[i] = true;
@@ -274,7 +307,7 @@ public:
/// Return a lower dimensional histogram
template <typename Iterator, typename = detail::is_iterator<Iterator>>
histogram reduce_to(Iterator begin, Iterator end) const {
dynamic_histogram reduce_to(Iterator begin, Iterator end) const {
std::vector<bool> b(dim(), false);
for (; begin != end; ++begin)
b[*begin] = true;
@@ -426,7 +459,7 @@ private:
}
}
histogram reduce_impl(const std::vector<bool> &b) const {
dynamic_histogram reduce_impl(const std::vector<bool> &b) const {
axes_type axes;
std::vector<unsigned> n(b.size());
auto axes_iter = axes_.begin();
@@ -438,7 +471,7 @@ private:
++axes_iter;
++n_iter;
}
histogram h(axes.begin(), axes.end());
dynamic_histogram h(axes.begin(), axes.end());
detail::index_mapper m(n, b);
do {
detail::storage_add(h.storage_, storage_, m.second, m.first);
@@ -446,43 +479,42 @@ private:
return h;
}
template <typename D, typename A, typename S> friend class histogram;
template <typename A, typename S> friend class dynamic_histogram;
template <typename A, typename S> friend class static_histogram;
friend class ::boost::python::access;
friend class ::boost::serialization::access;
template <typename Archive> void serialize(Archive &, unsigned);
};
template <typename... Axes>
histogram<Dynamic, detail::combine_t<axis::builtins, mpl::vector<Axes...>>>
dynamic_histogram<detail::combine_t<axis::builtins, mpl::vector<Axes...>>>
make_dynamic_histogram(Axes &&... axes) {
return histogram<Dynamic,
return dynamic_histogram<
detail::combine_t<axis::builtins, mpl::vector<Axes...>>>(
std::forward<Axes>(axes)...);
}
template <typename Storage, typename... Axes>
histogram<Dynamic, detail::combine_t<axis::builtins, mpl::vector<Axes...>>,
dynamic_histogram<detail::combine_t<axis::builtins, mpl::vector<Axes...>>,
Storage>
make_dynamic_histogram_with(Axes &&... axes) {
return histogram<
Dynamic, detail::combine_t<axis::builtins, mpl::vector<Axes...>>, Storage>(
return dynamic_histogram<
detail::combine_t<axis::builtins, mpl::vector<Axes...>>, Storage>(
std::forward<Axes>(axes)...);
}
template <typename Iterator, typename = detail::is_iterator<Iterator>>
histogram<Dynamic, detail::combine_t<axis::builtins, typename Iterator::value_type::types>>
dynamic_histogram<detail::combine_t<axis::builtins, typename Iterator::value_type::types>>
make_dynamic_histogram(Iterator begin, Iterator end) {
return histogram<
Dynamic, detail::combine_t<axis::builtins, typename Iterator::value_type::types>>(
return dynamic_histogram<detail::combine_t<axis::builtins, typename Iterator::value_type::types>>(
begin, end);
}
template <typename Storage, typename Iterator, typename = detail::is_iterator<Iterator>>
histogram<Dynamic, detail::combine_t<axis::builtins, typename Iterator::value_type::types>, Storage>
dynamic_histogram<detail::combine_t<axis::builtins, typename Iterator::value_type::types>, Storage>
make_dynamic_histogram_with(Iterator begin, Iterator end) {
return histogram<
Dynamic, detail::combine_t<axis::builtins, typename Iterator::value_type::types>, Storage>(
return dynamic_histogram<detail::combine_t<axis::builtins, typename Iterator::value_type::types>, Storage>(
begin, end);
}

View File

@@ -7,8 +7,8 @@
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_HPP_
#include <boost/histogram/histogram_impl_dynamic.hpp>
#include <boost/histogram/histogram_impl_static.hpp>
#include <boost/histogram/histogram_arithmetic_operators.hpp>
#include <boost/histogram/dynamic_histogram.hpp>
#include <boost/histogram/static_histogram.hpp>
#include <boost/histogram/arithmetic_operators.hpp>
#endif

View File

@@ -1,96 +0,0 @@
// Copyright 2015-2016 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_ARITHMETIC_OPERATORS_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_ARITHMETIC_OPERATORS_HPP_
#include <boost/histogram/histogram_fwd.hpp>
namespace boost {
namespace histogram {
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator+(histogram<Variant, Axes, Storage> &&a,
const histogram<Variant, Axes, Storage> &b) {
a += b;
return std::move(a);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator+(histogram<Variant, Axes, Storage> &&a,
histogram<Variant, Axes, Storage> &&b) {
a += b;
return std::move(a);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator+(const histogram<Variant, Axes, Storage> &a,
histogram<Variant, Axes, Storage> &&b) {
b += a;
return std::move(b);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>
operator+(const histogram<Variant, Axes, Storage> &a,
const histogram<Variant, Axes, Storage> &b) {
histogram<Variant, Axes, Storage> r(a);
r += b;
return r;
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator*(histogram<Variant, Axes, Storage> &&a, const double x) {
a *= x;
return std::move(a);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator*(const double x, histogram<Variant, Axes, Storage> &&b) {
b *= x;
return std::move(b);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>
operator*(const histogram<Variant, Axes, Storage> &a, const double x) {
histogram<Variant, Axes, Storage> r(a);
r *= x;
return r;
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>
operator*(const double x, const histogram<Variant, Axes, Storage> &b) {
histogram<Variant, Axes, Storage> r(b);
r *= x;
return r;
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> &&
operator/(histogram<Variant, Axes, Storage> &&a, const double x) {
a /= x;
return std::move(a);
}
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>
operator/(const histogram<Variant, Axes, Storage> &a, const double x) {
histogram<Variant, Axes, Storage> r(a);
r /= x;
return r;
}
} // namespace histogram
} // namespace boost
#endif

View File

@@ -7,17 +7,12 @@
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_FWD_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_FWD_HPP_
#include <boost/histogram/detail/meta.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/vector.hpp>
#include <set>
#include <string>
namespace boost {
namespace histogram {
using Static = std::integral_constant<int, 0>;
using Dynamic = std::integral_constant<int, 1>;
class adaptive_storage;
namespace axis {
@@ -43,10 +38,17 @@ using builtins =
axis::regular<double, axis::transform::pow>, axis::circular<>,
axis::variable<>, axis::integer<>,
axis::category<>, axis::category<std::string>>;
}
template <class Variant, class Axes, class Storage = adaptive_storage>
class histogram;
template <typename Axes = builtins>
class any;
} // namespace axis
template <class Axes, class Storage = adaptive_storage>
class static_histogram;
template <class Axes, class Storage = adaptive_storage>
class dynamic_histogram;
struct weight {
weight(double w) : value(w) {}

View File

@@ -4,11 +4,10 @@
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_OSTREAM_OPERATORS_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_OSTREAM_OPERATORS_HPP_
#ifndef _BOOST_HISTOGRAM_OSTREAM_OPERATORS_HPP_
#define _BOOST_HISTOGRAM_OSTREAM_OPERATORS_HPP_
#include <boost/histogram/axis_ostream_operators.hpp>
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/histogram/axis/ostream_operators.hpp>
#include <ostream>
namespace boost {
@@ -24,8 +23,8 @@ struct axis_ostream_visitor {
};
} // namespace detail
template <typename D, typename A, typename S>
inline std::ostream &operator<<(std::ostream &os, const histogram<D, A, S> &h) {
template <template <class, class> class H, typename A, typename S>
inline std::ostream &operator<<(std::ostream &os, const H<A, S> &h) {
os << "histogram(";
detail::axis_ostream_visitor sh(os);
h.for_each_axis(sh);

View File

@@ -192,7 +192,7 @@ void any<Axes>::serialize(Archive &ar, unsigned /* version */) {
template <class A, class S>
template <class Archive>
void histogram<Static, A, S>::serialize(Archive &ar, unsigned /* version */) {
void static_histogram<A, S>::serialize(Archive &ar, unsigned /* version */) {
detail::serialize_helper<Archive> sh(ar);
fusion::for_each(axes_, sh);
ar &storage_;
@@ -200,7 +200,7 @@ void histogram<Static, A, S>::serialize(Archive &ar, unsigned /* version */) {
template <class A, class S>
template <class Archive>
void histogram<Dynamic, A, S>::serialize(Archive &ar, unsigned /* version */) {
void dynamic_histogram<A, S>::serialize(Archive &ar, unsigned /* version */) {
ar &axes_;
ar &storage_;
}

View File

@@ -19,7 +19,7 @@
#include <boost/fusion/include/sequence.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/fusion/sequence/comparison.hpp>
#include <boost/histogram/axis.hpp>
#include <boost/histogram/axis/axis.hpp>
#include <boost/histogram/detail/axis_visitor.hpp>
#include <boost/histogram/detail/meta.hpp>
#include <boost/histogram/detail/utility.hpp>
@@ -42,7 +42,7 @@ namespace boost {
namespace histogram {
template <typename Axes, typename Storage>
class histogram<Static, Axes, Storage> {
class static_histogram {
static_assert(!mpl::empty<Axes>::value, "at least one axis required");
using axes_size = typename fusion::result_of::size<Axes>::type;
@@ -50,28 +50,33 @@ public:
using axes_type = typename fusion::result_of::as_vector<Axes>::type;
using value_type = typename Storage::value_type;
histogram() = default;
histogram(const histogram &rhs) = default;
histogram(histogram &&rhs) = default;
histogram &operator=(const histogram &rhs) = default;
histogram &operator=(histogram &&rhs) = default;
static_histogram() = default;
static_histogram(const static_histogram &rhs) = default;
static_histogram(static_histogram &&rhs) = default;
static_histogram &operator=(const static_histogram &rhs) = default;
static_histogram &operator=(static_histogram &&rhs) = default;
template <typename... Axis>
explicit histogram(const Axis &... axis) : axes_(axis...) {
explicit static_histogram(const Axis &... axis) : axes_(axis...) {
storage_ = Storage(bincount_from_axes());
}
explicit histogram(axes_type &&axes) : axes_(std::move(axes)) {
explicit static_histogram(axes_type &&axes) : axes_(std::move(axes)) {
storage_ = Storage(bincount_from_axes());
}
template <typename D, typename A, typename S>
explicit histogram(const histogram<D, A, S> &rhs) : storage_(rhs.storage_) {
template <typename S>
explicit static_histogram(const static_histogram<Axes, S> &rhs) : storage_(rhs.storage_) {
detail::axes_assign(axes_, rhs.axes_);
}
template <typename D, typename A, typename S>
histogram &operator=(const histogram<D, A, S> &rhs) {
template <typename A, typename S>
explicit static_histogram(const dynamic_histogram<A, S> &rhs) : storage_(rhs.storage_) {
detail::axes_assign(axes_, rhs.axes_);
}
template <typename S>
static_histogram &operator=(const static_histogram<Axes, S> &rhs) {
if (static_cast<const void *>(this) != static_cast<const void *>(&rhs)) {
detail::axes_assign(axes_, rhs.axes_);
storage_ = rhs.storage_;
@@ -79,30 +84,62 @@ public:
return *this;
}
template <typename D, typename A, typename S>
bool operator==(const histogram<D, A, S> &rhs) const {
template <typename A, typename S>
static_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_;
}
return *this;
}
template <typename A, typename S>
bool operator==(const static_histogram<A, S> &rhs) const noexcept {
return false;
}
template <typename S>
bool operator==(const static_histogram<Axes, S> &rhs) const noexcept {
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
}
template <typename D, typename A, typename S>
bool operator!=(const histogram<D, A, S> &rhs) const {
template <typename A, typename S>
bool operator==(const dynamic_histogram<A, S> &rhs) const noexcept {
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
}
template <typename A, typename S>
bool operator!=(const static_histogram<A, S> &rhs) const noexcept {
return !operator==(rhs);
}
template <typename D, typename A, typename S>
histogram &operator+=(const histogram<D, A, S> &rhs) {
template <typename A, typename S>
bool operator!=(const dynamic_histogram<A, S> &rhs) const noexcept {
return !operator==(rhs);
}
template <typename S>
static_histogram &operator+=(const static_histogram<Axes, S> &rhs) {
if (!detail::axes_equal(axes_, rhs.axes_))
throw std::logic_error("axes of histograms differ");
storage_ += rhs.storage_;
return *this;
}
histogram &operator*=(const value_type rhs) {
template <typename A, typename S>
static_histogram &operator+=(const dynamic_histogram<A, S> &rhs) {
if (!detail::axes_equal(axes_, rhs.axes_))
throw std::logic_error("axes of histograms differ");
storage_ += rhs.storage_;
return *this;
}
static_histogram &operator*=(const value_type rhs) {
storage_ *= rhs;
return *this;
}
histogram &operator/=(const value_type rhs) {
static_histogram &operator/=(const value_type rhs) {
storage_ *= 1.0 / rhs;
return *this;
}
@@ -199,8 +236,8 @@ public:
/// Returns a lower-dimensional histogram
template <int N, typename... Rest>
auto reduce_to(mpl::int_<N>, Rest...) const
-> histogram<Static, detail::axes_select<Axes, mpl::vector<mpl::int_<N>, Rest...>>, Storage> {
using HR = histogram<Static, detail::axes_select<Axes, mpl::vector<mpl::int_<N>, Rest...>>, Storage>;
-> static_histogram<detail::axes_select<Axes, mpl::vector<mpl::int_<N>, Rest...>>, Storage> {
using HR = static_histogram<detail::axes_select<Axes, mpl::vector<mpl::int_<N>, Rest...>>, Storage>;
typename HR::axes_type axes;
detail::axes_assign_subset<mpl::vector<mpl::int_<N>, Rest...>>(axes, axes_);
auto hr = HR(std::move(axes));
@@ -323,25 +360,26 @@ private:
} while (m.next());
}
template <typename D, typename A, typename S> friend class histogram;
template <typename A, typename S> friend class static_histogram;
template <typename A, typename S> friend class dynamic_histogram;
friend class ::boost::serialization::access;
template <typename Archive> void serialize(Archive &, unsigned);
};
/// default static type factory
template <typename... Axis>
inline histogram<Static, mpl::vector<Axis...>>
inline static_histogram<mpl::vector<Axis...>>
make_static_histogram(Axis &&... axis) {
using h = histogram<Static, mpl::vector<Axis...>>;
using h = static_histogram<mpl::vector<Axis...>>;
auto axes = typename h::axes_type(std::forward<Axis>(axis)...);
return h(std::move(axes));
}
/// static type factory with variable storage type
template <typename Storage, typename... Axis>
inline histogram<Static, mpl::vector<Axis...>, Storage>
inline static_histogram<mpl::vector<Axis...>, Storage>
make_static_histogram_with(Axis &&... axis) {
using h = histogram<Static, mpl::vector<Axis...>, Storage>;
using h = static_histogram<mpl::vector<Axis...>, Storage>;
auto axes = typename h::axes_type(std::forward<Axis>(axis)...);
return h(std::move(axes));
}