mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 23:04:07 +00:00
Separate serialization code from Boost.Serialization
This commit is contained in:
parent
d68cc4729c
commit
9dd4a04a10
@ -51,5 +51,5 @@ test_script:
|
||||
|
||||
## Uncomment the following to stop VM and enable interactive login.
|
||||
## Instructions how to log into the Appveyor VM are automatically printed.
|
||||
# on_failure:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
on_failure:
|
||||
- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
@ -8,7 +8,10 @@
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_MEAN_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/fwd.hpp> // for mean<>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
@ -24,10 +27,10 @@ template <class RealType>
|
||||
class mean {
|
||||
public:
|
||||
mean() = default;
|
||||
mean(const RealType& n, const RealType& mean, const RealType& variance)
|
||||
mean(const RealType& n, const RealType& mean, const RealType& variance) noexcept
|
||||
: sum_(n), mean_(mean), sum_of_deltas_squared_(variance * (n - 1)) {}
|
||||
|
||||
void operator()(const RealType& x) {
|
||||
void operator()(const RealType& x) noexcept {
|
||||
sum_ += static_cast<RealType>(1);
|
||||
const auto delta = x - mean_;
|
||||
BOOST_ASSERT(sum_ != 0);
|
||||
@ -35,7 +38,7 @@ public:
|
||||
sum_of_deltas_squared_ += delta * (x - mean_);
|
||||
}
|
||||
|
||||
void operator()(const RealType& w, const RealType& x) {
|
||||
void operator()(const RealType& w, const RealType& x) noexcept {
|
||||
sum_ += w;
|
||||
const auto delta = x - mean_;
|
||||
BOOST_ASSERT(sum_ != 0);
|
||||
@ -44,7 +47,7 @@ public:
|
||||
}
|
||||
|
||||
template <class T>
|
||||
mean& operator+=(const mean<T>& rhs) {
|
||||
mean& operator+=(const mean<T>& rhs) noexcept {
|
||||
const auto tmp = mean_ * sum_ + static_cast<RealType>(rhs.mean_ * rhs.sum_);
|
||||
sum_ += rhs.sum_;
|
||||
BOOST_ASSERT(sum_ != 0);
|
||||
@ -53,7 +56,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
mean& operator*=(const RealType& s) {
|
||||
mean& operator*=(const RealType& s) noexcept {
|
||||
mean_ *= s;
|
||||
sum_of_deltas_squared_ *= s * s;
|
||||
return *this;
|
||||
@ -72,10 +75,22 @@ public:
|
||||
|
||||
const RealType& count() const noexcept { return sum_; }
|
||||
const RealType& value() const noexcept { return mean_; }
|
||||
RealType variance() const { return sum_of_deltas_squared_ / (sum_ - 1); }
|
||||
RealType variance() const noexcept { return sum_of_deltas_squared_ / (sum_ - 1); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
void serialize(Archive& ar, unsigned version) {
|
||||
if (version == 0) {
|
||||
if (Archive::is_saving::value)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("save must not use version 0"));
|
||||
std::size_t sum;
|
||||
ar& make_nvp("sum", sum);
|
||||
sum_ = static_cast<RealType>(sum);
|
||||
} else {
|
||||
ar& make_nvp("sum", sum_);
|
||||
}
|
||||
ar& make_nvp("mean", mean_);
|
||||
ar& make_nvp("sum_of_deltas_squared", sum_of_deltas_squared_);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType sum_ = 0, mean_ = 0, sum_of_deltas_squared_ = 0;
|
||||
@ -86,6 +101,21 @@ private:
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template <class T>
|
||||
struct version;
|
||||
|
||||
// version 1 for boost::histogram::accumulators::mean<RealType>
|
||||
template <class RealType>
|
||||
struct version<boost::histogram::accumulators::mean<RealType>>
|
||||
: std::integral_constant<int, 1> {};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
namespace std {
|
||||
template <class T, class U>
|
||||
/// Specialization for boost::histogram::accumulators::mean.
|
||||
@ -94,6 +124,7 @@ struct common_type<boost::histogram::accumulators::mean<T>,
|
||||
using type = boost::histogram::accumulators::mean<common_type_t<T, U>>;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,8 @@
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/fwd.hpp> // for sum<>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
@ -83,7 +84,10 @@ public:
|
||||
operator RealType() const { return large_ + small_; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("large", large_);
|
||||
ar& make_nvp("small", small_);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType large_ = RealType();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_THREAD_SAFE_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
@ -48,6 +49,13 @@ public:
|
||||
|
||||
void operator+=(T arg) { super_t::fetch_add(arg, std::memory_order_relaxed); }
|
||||
void operator++() { operator+=(static_cast<T>(1)); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
auto value = super_t::load();
|
||||
ar& make_nvp("value", value);
|
||||
super_t::store(value);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
|
@ -8,7 +8,8 @@
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_MEAN_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/fwd.hpp> // for weighted_mean<>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
@ -84,7 +85,12 @@ public:
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
ar& make_nvp("weighted_mean", weighted_mean_);
|
||||
ar& make_nvp("sum_of_weighted_deltas_squared", sum_of_weighted_deltas_squared_);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType sum_of_weights_ = RealType(), sum_of_weights_squared_ = RealType(),
|
||||
|
@ -7,7 +7,8 @@
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_SUM_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_SUM_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/fwd.hpp> // for weighted_sum<>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
@ -78,7 +79,10 @@ public:
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType sum_of_weights_ = RealType();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define BOOST_HISTOGRAM_AXIS_CATEGORY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
@ -175,7 +176,10 @@ public:
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("seq", vec_meta_.first());
|
||||
ar& make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vector_type, metadata_type> vec_meta_;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
@ -184,7 +185,11 @@ public:
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("size", size_meta_.first());
|
||||
ar& make_nvp("meta", size_meta_.second());
|
||||
ar& make_nvp("min", min_);
|
||||
}
|
||||
|
||||
private:
|
||||
index_type index_impl(std::false_type, int x) const noexcept {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define BOOST_HISTOGRAM_AXIS_REGULAR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
@ -77,6 +78,9 @@ struct id {
|
||||
static T inverse(T&& x) noexcept {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */) {}
|
||||
};
|
||||
|
||||
/// Log transform for equidistant bins in log-space.
|
||||
@ -92,6 +96,9 @@ struct log {
|
||||
static T inverse(T x) {
|
||||
return std::exp(x);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */) {}
|
||||
};
|
||||
|
||||
/// Sqrt transform for equidistant bins in sqrt-space.
|
||||
@ -107,6 +114,9 @@ struct sqrt {
|
||||
static T inverse(T x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */) {}
|
||||
};
|
||||
|
||||
/// Pow transform for equidistant bins in pow-space.
|
||||
@ -130,6 +140,11 @@ struct pow {
|
||||
}
|
||||
|
||||
bool operator==(const pow& o) const noexcept { return power == o.power; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("power", power);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace transform
|
||||
@ -384,7 +399,13 @@ public:
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("transform", static_cast<transform_type&>(*this));
|
||||
ar& make_nvp("size", size_meta_.first());
|
||||
ar& make_nvp("meta", size_meta_.second());
|
||||
ar& make_nvp("min", min_);
|
||||
ar& make_nvp("delta", delta_);
|
||||
}
|
||||
|
||||
private:
|
||||
detail::compressed_pair<index_type, metadata_type> size_meta_{0};
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
@ -226,7 +227,10 @@ public:
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("seq", vec_meta_.first());
|
||||
ar& make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vec_type, metadata_type> vec_meta_;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
// Copyright 2015-2019 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/polymorphic_bin.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
@ -14,10 +15,9 @@
|
||||
#include <boost/histogram/detail/relaxed_equal.hpp>
|
||||
#include <boost/histogram/detail/static_if.hpp>
|
||||
#include <boost/histogram/detail/type_name.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <boost/histogram/detail/variant_proxy.hpp>
|
||||
#include <boost/mp11/algorithm.hpp> // mp_contains
|
||||
#include <boost/mp11/list.hpp> // mp_first
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <ostream>
|
||||
@ -219,6 +219,12 @@ public:
|
||||
return !operator==(t);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
detail::variant_proxy<variant> p{*this};
|
||||
ar& make_nvp("variant", p);
|
||||
}
|
||||
|
||||
private:
|
||||
impl_type impl;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/make_default.hpp>
|
||||
@ -179,6 +180,24 @@ void axes_assign(T& t, const U& u) {
|
||||
t.assign(u.begin(), u.end());
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void axes_serialize(Archive& ar, T& axes) {
|
||||
ar& make_nvp("axes", axes);
|
||||
}
|
||||
|
||||
template <class Archive, class... Ts>
|
||||
void axes_serialize(Archive& ar, std::tuple<Ts...>& axes) {
|
||||
// needed to keep serialization format backward compatible
|
||||
struct proxy {
|
||||
std::tuple<Ts...>& t;
|
||||
void serialize(Archive& ar, unsigned) {
|
||||
mp11::tuple_for_each(t, [&ar](auto& x) { ar& make_nvp("item", x); });
|
||||
}
|
||||
};
|
||||
proxy p{axes};
|
||||
ar& make_nvp("axes", p);
|
||||
}
|
||||
|
||||
// create empty dynamic axis which can store any axes types from the argument
|
||||
template <class T>
|
||||
auto make_empty_dynamic_axes(const T& axes) {
|
||||
|
@ -229,8 +229,8 @@ void fill_n_1(const std::size_t offset, S& storage, A& axes, const std::size_t v
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t get_total_size(const dtl::span<const T>& values) {
|
||||
template <class T, std::size_t N>
|
||||
std::size_t get_total_size(const dtl::span<const T, N>& values) {
|
||||
std::size_t s = 1u;
|
||||
auto vis = [&s](const auto& v) {
|
||||
// cannot be replaced by std::decay_t
|
||||
@ -261,9 +261,9 @@ void fill_n_check_extra_args(std::size_t n, Ts&&... ts) {
|
||||
|
||||
inline void fill_n_check_extra_args(std::size_t) noexcept {}
|
||||
|
||||
template <class S, class A, class T, class... Us>
|
||||
template <class S, class A, class T, std::size_t N, class... Us>
|
||||
void fill_n(const std::size_t offset, S& storage, A& axes,
|
||||
const dtl::span<const T> values, Us&&... us) {
|
||||
const dtl::span<const T, N> values, Us&&... us) {
|
||||
static_assert(!std::is_pointer<T>::value,
|
||||
"passing iterable of pointers not allowed (cannot determine lengths); "
|
||||
"pass iterable of iterables instead");
|
||||
|
@ -217,6 +217,11 @@ struct large_int : totally_ordered<large_int<Allocator>, large_int<Allocator>>,
|
||||
--d -= tmp;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("data", data);
|
||||
}
|
||||
|
||||
std::vector<std::uint64_t, Allocator> data;
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,11 @@
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_SPAN_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_SPAN_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/detail/static_if.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#if __cpp_constexpr >= 201603 && __cpp_deduction_guides >= 201703 && \
|
||||
__cpp_lib_nonmember_container_access >= 201411 && __has_include(<span>)
|
||||
#include <span>
|
||||
@ -240,7 +245,12 @@ auto make_span(const Container& cont) {
|
||||
|
||||
template <class T, std::size_t N>
|
||||
auto make_span(T (&arr)[N]) {
|
||||
return dtl::span<T>(arr, N);
|
||||
return dtl::span<T, N>(arr, N);
|
||||
}
|
||||
|
||||
template <class Archive, class T, std::size_t N>
|
||||
void serialize(Archive& ar, dtl::span<T, N>& sp, unsigned /* version */) {
|
||||
for (auto&& x : sp) ar& make_nvp("item", x);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
67
include/boost/histogram/detail/variant_proxy.hpp
Normal file
67
include/boost/histogram/detail/variant_proxy.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2019 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_DETAIL_VARIANT_PROXY_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_VARIANT_PROXY_HPP
|
||||
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp> // variant_access
|
||||
#include <boost/histogram/detail/static_if.hpp>
|
||||
#include <boost/mp11/algorithm.hpp> // mp_with_index, mp_find, mp_at
|
||||
#include <boost/mp11/list.hpp> // mp_size
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
// This is a workaround to remain backward compatible in the serialization format. The
|
||||
// proxy uses only the public interface of axis::variant for serialization and works
|
||||
// independently of the underlying variant implementation.
|
||||
template <class Variant>
|
||||
struct variant_proxy {
|
||||
Variant& variant;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
detail::static_if_c<Archive::is_loading::value>(
|
||||
[this](auto& ar) { // loading
|
||||
int which = 0;
|
||||
ar >> make_nvp("which", which);
|
||||
constexpr unsigned N = mp11::mp_size<Variant>::value;
|
||||
if (which < 0 || static_cast<unsigned>(which) >= N)
|
||||
// throw if which >= N, can happen if type was removed from variant
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::runtime_error("variant has fewer types than stored version"));
|
||||
mp11::mp_with_index<N>(static_cast<unsigned>(which), [&ar, this](auto i) {
|
||||
using T = mp11::mp_at_c<Variant, i>;
|
||||
T value;
|
||||
ar >> make_nvp("value", value);
|
||||
this->variant = std::move(value);
|
||||
T* new_address = variant_access::template get_if<T>(&this->variant);
|
||||
ar.reset_object_address(new_address, &value);
|
||||
});
|
||||
},
|
||||
[this](auto& ar) { // saving
|
||||
visit(
|
||||
[&ar](const auto& value) {
|
||||
using T = std::decay_t<decltype(value)>;
|
||||
const int which = static_cast<int>(mp11::mp_find<Variant, T>::value);
|
||||
ar << make_nvp("which", which);
|
||||
ar << make_nvp("value", value);
|
||||
},
|
||||
this->variant);
|
||||
},
|
||||
ar);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
@ -38,6 +38,9 @@ using empty_type = null_type;
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, null_type&, unsigned /* version */) {}
|
||||
|
||||
namespace transform {
|
||||
struct id;
|
||||
struct log;
|
||||
|
@ -503,6 +503,16 @@ public:
|
||||
/// Return value iterator to the end in the histogram (read-only).
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
detail::axes_serialize(ar, axes_);
|
||||
ar& make_nvp("storage", storage_and_mutex_.first());
|
||||
if (Archive::is_loading::value) {
|
||||
offset_ = detail::offset(axes_);
|
||||
detail::throw_if_axes_is_too_large(axes_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
axes_type axes_;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
// Copyright 2015-2019 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@ -7,278 +7,17 @@
|
||||
#ifndef BOOST_HISTOGRAM_SERIALIZATION_HPP
|
||||
#define BOOST_HISTOGRAM_SERIALIZATION_HPP
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/accumulators/mean.hpp>
|
||||
#include <boost/histogram/accumulators/sum.hpp>
|
||||
#include <boost/histogram/accumulators/weighted_mean.hpp>
|
||||
#include <boost/histogram/accumulators/weighted_sum.hpp>
|
||||
#include <boost/histogram/axis/category.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/axis/variable.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include <boost/histogram/unlimited_storage.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
\file boost/histogram/serialization.hpp
|
||||
|
||||
Implemenations of the serialization functions using
|
||||
[Boost.Serialization](https://www.boost.org/doc/libs/develop/libs/serialization/doc/index.html).
|
||||
Headers from
|
||||
[Boost.Serialization](https://www.boost.org/doc/libs/develop/libs/serialization/doc/index.html)
|
||||
needed to serialize STL types that are used internally by the Boost.Histogram classes.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
// version 1 for boost::histogram::accumulators::mean<RealType>
|
||||
template <class RealType>
|
||||
struct version<boost::histogram::accumulators::mean<RealType>> {
|
||||
typedef mpl::int_<1> type;
|
||||
typedef mpl::integral_c_tag tag;
|
||||
BOOST_STATIC_CONSTANT(int, value = version::type::value);
|
||||
};
|
||||
|
||||
template <class Archive, class... Ts>
|
||||
void serialize(Archive& ar, std::tuple<Ts...>& t, unsigned /* version */) {
|
||||
mp11::tuple_for_each(t, [&ar](auto& x) { ar& make_nvp("item", x); });
|
||||
}
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
namespace accumulators {
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("large", large_);
|
||||
ar& make_nvp("small", small_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void weighted_sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void mean<RealType>::serialize(Archive& ar, unsigned version) {
|
||||
if (version == 0 && Archive::is_loading::value) {
|
||||
std::size_t sum;
|
||||
ar& make_nvp("sum", sum);
|
||||
sum_ = static_cast<RealType>(sum);
|
||||
} else {
|
||||
ar& make_nvp("sum", sum_);
|
||||
}
|
||||
ar& make_nvp("mean", mean_);
|
||||
ar& make_nvp("sum_of_deltas_squared", sum_of_deltas_squared_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void weighted_mean<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
ar& make_nvp("weighted_mean", weighted_mean_);
|
||||
ar& make_nvp("sum_of_weighted_deltas_squared", sum_of_weighted_deltas_squared_);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, thread_safe<T>& t, unsigned /* version */) {
|
||||
T value = t;
|
||||
ar& make_nvp("value", value);
|
||||
t = value;
|
||||
}
|
||||
} // namespace accumulators
|
||||
|
||||
namespace axis {
|
||||
|
||||
namespace transform {
|
||||
template <class Archive>
|
||||
void serialize(Archive&, id&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, log&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, sqrt&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, pow& t, unsigned /* version */) {
|
||||
ar& make_nvp("power", t.power);
|
||||
}
|
||||
} // namespace transform
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, null_type&, unsigned /* version */) {}
|
||||
|
||||
template <class T, class Tr, class M, class O>
|
||||
template <class Archive>
|
||||
void regular<T, Tr, M, O>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("transform", static_cast<transform_type&>(*this));
|
||||
ar& make_nvp("size", size_meta_.first());
|
||||
ar& make_nvp("meta", size_meta_.second());
|
||||
ar& make_nvp("min", min_);
|
||||
ar& make_nvp("delta", delta_);
|
||||
}
|
||||
|
||||
template <class T, class M, class O>
|
||||
template <class Archive>
|
||||
void integer<T, M, O>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("size", size_meta_.first());
|
||||
ar& make_nvp("meta", size_meta_.second());
|
||||
ar& make_nvp("min", min_);
|
||||
}
|
||||
|
||||
template <class T, class M, class O, class A>
|
||||
template <class Archive>
|
||||
void variable<T, M, O, A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("seq", vec_meta_.first());
|
||||
ar& make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
template <class T, class M, class O, class A>
|
||||
template <class Archive>
|
||||
void category<T, M, O, A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("seq", vec_meta_.first());
|
||||
ar& make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
// variant_proxy is a workaround to remain backward compatible in the serialization
|
||||
// format. It uses only the public interface of axis::variant for serialization and
|
||||
// therefore works independently of the underlying variant implementation.
|
||||
template <class Variant>
|
||||
struct variant_proxy {
|
||||
Variant& v;
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
template <class Archive>
|
||||
void save(Archive& ar, unsigned /* version */) const {
|
||||
visit(
|
||||
[&ar](auto& value) {
|
||||
using T = std::decay_t<decltype(value)>;
|
||||
int which = static_cast<int>(mp11::mp_find<Variant, T>::value);
|
||||
ar << make_nvp("which", which);
|
||||
ar << make_nvp("value", value);
|
||||
},
|
||||
v);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load(Archive& ar, unsigned /* version */) {
|
||||
int which = 0;
|
||||
ar >> make_nvp("which", which);
|
||||
constexpr unsigned N = mp11::mp_size<Variant>::value;
|
||||
if (which < 0 || static_cast<unsigned>(which) >= N)
|
||||
// throw on invalid which, which >= N can happen if type was removed from variant
|
||||
serialization::throw_exception(
|
||||
archive::archive_exception(archive::archive_exception::unsupported_version));
|
||||
mp11::mp_with_index<N>(static_cast<unsigned>(which), [&ar, this](auto i) {
|
||||
using T = mp11::mp_at_c<Variant, i>;
|
||||
T value;
|
||||
ar >> make_nvp("value", value);
|
||||
v = std::move(value);
|
||||
T* new_address = get_if<T>(&v);
|
||||
ar.reset_object_address(new_address, &value);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
template <class Archive, class... Ts>
|
||||
void serialize(Archive& ar, variant<Ts...>& v, unsigned /* version */) {
|
||||
variant_proxy<variant<Ts...>> p{v};
|
||||
ar& make_nvp("variant", p);
|
||||
}
|
||||
} // namespace axis
|
||||
|
||||
namespace detail {
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, vector_impl<T>& impl, unsigned /* version */) {
|
||||
ar& make_nvp("vector", static_cast<T&>(impl));
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, array_impl<T>& impl, unsigned /* version */) {
|
||||
ar& make_nvp("size", impl.size_);
|
||||
ar& make_nvp("array", serialization::make_array(impl.data(), impl.size_));
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, map_impl<T>& impl, unsigned /* version */) {
|
||||
ar& make_nvp("size", impl.size_);
|
||||
ar& make_nvp("map", static_cast<T&>(impl));
|
||||
}
|
||||
|
||||
template <class Archive, class Allocator>
|
||||
void serialize(Archive& ar, large_int<Allocator>& x, unsigned /* version */) {
|
||||
ar& make_nvp("data", x.data);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, storage_adaptor<T>& x, unsigned /* version */) {
|
||||
auto& impl = unsafe_access::storage_adaptor_impl(x);
|
||||
ar& make_nvp("impl", impl);
|
||||
}
|
||||
|
||||
template <class Allocator, class Archive>
|
||||
void serialize(Archive& ar, unlimited_storage<Allocator>& s, unsigned /* version */) {
|
||||
auto& buffer = unsafe_access::unlimited_storage_buffer(s);
|
||||
using buffer_t = std::remove_reference_t<decltype(buffer)>;
|
||||
if (Archive::is_loading::value) {
|
||||
buffer_t helper(buffer.alloc);
|
||||
std::size_t size;
|
||||
ar& make_nvp("type", helper.type);
|
||||
ar& make_nvp("size", size);
|
||||
helper.visit([&buffer, size](auto* tp) {
|
||||
BOOST_ASSERT(tp == nullptr);
|
||||
using T = std::decay_t<decltype(*tp)>;
|
||||
buffer.template make<T>(size);
|
||||
});
|
||||
} else {
|
||||
ar& make_nvp("type", buffer.type);
|
||||
ar& make_nvp("size", buffer.size);
|
||||
}
|
||||
buffer.visit([&buffer, &ar](auto* tp) {
|
||||
ar& make_nvp("buffer", serialization::make_array(
|
||||
static_cast<decltype(tp)>(buffer.ptr), buffer.size));
|
||||
});
|
||||
}
|
||||
|
||||
template <class Archive, class A, class S>
|
||||
void serialize(Archive& ar, histogram<A, S>& h, unsigned /* version */) {
|
||||
ar& make_nvp("axes", unsafe_access::axes(h));
|
||||
ar& make_nvp("storage", unsafe_access::storage(h));
|
||||
if (Archive::is_loading::value) {
|
||||
unsafe_access::offset(h) = detail::offset(unsafe_access::axes(h));
|
||||
detail::throw_if_axes_is_too_large(unsafe_access::axes(h));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -8,14 +8,15 @@
|
||||
#define BOOST_HISTOGRAM_STORAGE_ADAPTOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/detect.hpp>
|
||||
#include <boost/histogram/detail/iterator_adaptor.hpp>
|
||||
#include <boost/histogram/detail/safe_comparison.hpp>
|
||||
#include <boost/histogram/detail/span.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
@ -57,7 +58,12 @@ struct vector_impl : T {
|
||||
T::resize(n, value_type());
|
||||
std::fill_n(T::begin(), (std::min)(n, old_size), value_type());
|
||||
}
|
||||
}; // namespace detail
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("vector", static_cast<T&>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct array_impl : T {
|
||||
@ -107,6 +113,13 @@ struct array_impl : T {
|
||||
|
||||
std::size_t size() const noexcept { return size_; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("size", size_);
|
||||
auto sp = detail::make_span(T::data(), size_);
|
||||
ar& make_nvp("array", sp);
|
||||
}
|
||||
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
@ -315,6 +328,12 @@ struct map_impl : T {
|
||||
|
||||
std::size_t size() const noexcept { return size_; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("size", size_);
|
||||
ar& make_nvp("map", static_cast<T&>(*this));
|
||||
}
|
||||
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
@ -363,6 +382,11 @@ public:
|
||||
return std::equal(this->begin(), this->end(), begin(u), end(u), detail::safe_equal{});
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("impl", static_cast<impl_type&>(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
friend struct unsafe_access;
|
||||
};
|
||||
|
@ -13,10 +13,12 @@
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/core/alloc_construct.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/detail/iterator_adaptor.hpp>
|
||||
#include <boost/histogram/detail/large_int.hpp>
|
||||
#include <boost/histogram/detail/operators.hpp>
|
||||
#include <boost/histogram/detail/safe_comparison.hpp>
|
||||
#include <boost/histogram/detail/span.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
@ -506,6 +508,28 @@ public:
|
||||
buffer_.template make<T>(s, p);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
if (Archive::is_loading::value) {
|
||||
buffer_type tmp(buffer_.alloc);
|
||||
std::size_t size;
|
||||
ar& make_nvp("type", tmp.type);
|
||||
ar& make_nvp("size", size);
|
||||
tmp.visit([this, size](auto* tp) {
|
||||
BOOST_ASSERT(tp == nullptr);
|
||||
using T = std::decay_t<decltype(*tp)>;
|
||||
buffer_.template make<T>(size);
|
||||
});
|
||||
} else {
|
||||
ar& make_nvp("type", buffer_.type);
|
||||
ar& make_nvp("size", buffer_.size);
|
||||
}
|
||||
buffer_.visit([this, &ar](auto* tp) {
|
||||
auto sp = detail::make_span(tp, buffer_.size);
|
||||
ar& make_nvp("buffer", sp);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
struct incrementor {
|
||||
template <class T>
|
||||
|
@ -4,6 +4,7 @@
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/archive/xml_oarchive.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram/accumulators.hpp>
|
||||
@ -24,6 +25,10 @@ int main(int argc, char** argv) {
|
||||
BOOST_TEST_EQ(a.count(), 3);
|
||||
BOOST_TEST_EQ(a.value(), 2);
|
||||
BOOST_TEST_EQ(a.variance(), 0.5);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
boost::archive::xml_oarchive oa(std::cout);
|
||||
BOOST_TEST_THROWS(a.serialize(oa, 0), std::runtime_error);
|
||||
#endif
|
||||
}
|
||||
|
||||
// mean
|
||||
|
@ -35,7 +35,7 @@ int main(int argc, char** argv) {
|
||||
BOOST_TEST_EQ(a, b);
|
||||
|
||||
variant<I> c; // load incompatible version
|
||||
BOOST_TEST_THROWS(load_xml(filename, c), boost::archive::archive_exception);
|
||||
BOOST_TEST_THROWS(load_xml(filename, c), std::runtime_error);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <boost/archive/xml_oarchive.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@ -39,14 +40,14 @@ void load_xml(const std::string& filename, T& t) {
|
||||
BOOST_ASSERT(std::strlen(line) < 127);
|
||||
} while (!ifs.fail() && !ifs.eof() && std::strstr(line, "-->") == nullptr);
|
||||
boost::archive::xml_iarchive ia(ifs);
|
||||
ia >> boost::serialization::make_nvp("item", t);
|
||||
ia >> boost::make_nvp("item", t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void print_xml(const std::string& filename, const T& t) {
|
||||
std::cout << filename << "\n";
|
||||
boost::archive::xml_oarchive oa(std::cout);
|
||||
oa << boost::serialization::make_nvp("item", t);
|
||||
oa << boost::make_nvp("item", t);
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
|
39
tools/tidy.py
Executable file
39
tools/tidy.py
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2019 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
|
||||
|
||||
import subprocess as subp
|
||||
from pathlib import Path
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
clang_tidy_cmd = None
|
||||
for version in range(15, 5, -1):
|
||||
clang_tidy_cmd = f"clang-tidy-{version}"
|
||||
if subp.run(("which", clang_tidy_cmd), stdout=subp.DEVNULL).returncode == 0:
|
||||
break
|
||||
|
||||
project_dir = Path(__file__).resolve().parents[1]
|
||||
assert project_dir.exists()
|
||||
boost_dir = project_dir.parents[1]
|
||||
|
||||
filenames = (project_dir / "include").rglob("*.hpp")
|
||||
|
||||
|
||||
def run_tidy(filename):
|
||||
n = len(project_dir.parts) + 2
|
||||
cmd = f"{clang_tidy_cmd} {filename} -- -I{boost_dir}"
|
||||
return (
|
||||
cmd,
|
||||
subp.run(cmd.split(), stdout=subp.PIPE, stderr=subp.STDOUT).stdout.decode(
|
||||
"utf-8"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
pool = ThreadPool()
|
||||
for cmd, report in pool.map(run_tidy, filenames):
|
||||
if report:
|
||||
print(cmd)
|
||||
print(report)
|
Loading…
x
Reference in New Issue
Block a user