mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
working version
This commit is contained in:
parent
a17a6c677c
commit
61be24b94d
@ -98,6 +98,7 @@ struct adaptive_storage {
|
||||
typename std::allocator_traits<Allocator>::value_type*>::value,
|
||||
"adaptive_storage requires allocator with trivial pointer type");
|
||||
|
||||
struct storage_tag {};
|
||||
using allocator_type = Allocator;
|
||||
using value_type = double;
|
||||
using const_reference = double;
|
||||
|
@ -96,9 +96,10 @@ BOOST_HISTOGRAM_MAKE_SFINAE(has_variance_support,
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_value, (std::declval<T&>().value(0)));
|
||||
|
||||
// TODO try casting to more specific pmf with correct return type
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_options, &T::options);
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_metadata, &T::metadata);
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_metadata, (std::declval<T&>().metadata()));
|
||||
|
||||
// resize has two overloads, trying to get pmf in this case always fails
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_resize, (std::declval<T&>().resize(0)));
|
||||
@ -107,6 +108,10 @@ BOOST_HISTOGRAM_MAKE_SFINAE(has_method_size, &T::size);
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_clear, &T::clear);
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(has_allocator, &T::get_allocator);
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(is_storage, (std::declval<typename T::storage_tag>()));
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(is_indexable, (std::declval<T&>()[0]));
|
||||
|
||||
BOOST_HISTOGRAM_MAKE_SFINAE(is_transform, (&T::forward, &T::inverse));
|
||||
@ -201,6 +206,9 @@ struct requires_same {};
|
||||
template <typename T, typename = mp11::mp_if<is_transform<T>, void>>
|
||||
struct requires_transform {};
|
||||
|
||||
template <typename T, typename = mp11::mp_if<is_storage<T>, void>>
|
||||
struct requires_storage {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/adaptive_storage.hpp> // implements default_storage
|
||||
#include <boost/histogram/arithmetic_operators.hpp>
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/index_mapper.hpp>
|
||||
@ -32,7 +33,8 @@ class histogram {
|
||||
public:
|
||||
using axes_type = Axes;
|
||||
using container_type = Container;
|
||||
using storage_type = storage_adaptor<Container>;
|
||||
using storage_type =
|
||||
mp11::mp_if<detail::is_storage<Container>, Container, storage_adaptor<Container>>;
|
||||
using value_type = typename storage_type::value_type;
|
||||
using const_reference = typename storage_type::const_reference;
|
||||
using const_iterator = iterator<histogram>;
|
||||
@ -205,7 +207,11 @@ public:
|
||||
using sub_axes_type = detail::sub_axes<axes_type, N, Ns...>;
|
||||
using HR = histogram<sub_axes_type, storage_type>;
|
||||
auto sub_axes = detail::make_sub_axes(axes_, N(), Ns()...);
|
||||
auto hr = HR(std::move(sub_axes), storage_type());
|
||||
// make something here to copy allocator if container has an allocator
|
||||
auto hr = HR(std::move(sub_axes),
|
||||
detail::static_if<detail::has_allocator<container_type>>(
|
||||
[this](auto) { return container_type(storage_.get_allocator()); },
|
||||
[](auto) { return container_type(); }, 0));
|
||||
const auto b = detail::bool_mask<N, Ns...>(rank(), true);
|
||||
std::vector<unsigned> shape(rank());
|
||||
for_each_axis(detail::shape_collector(shape.begin()));
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/adaptive_storage.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <map>
|
||||
@ -83,6 +82,7 @@ struct storage_adaptor : detail::storage_reset<T> {
|
||||
using base_type::base_type;
|
||||
using value_type = typename T::value_type;
|
||||
using const_reference = typename T::const_reference;
|
||||
struct storage_tag {};
|
||||
|
||||
storage_adaptor() = default;
|
||||
storage_adaptor(const storage_adaptor&) = default;
|
||||
@ -93,16 +93,15 @@ struct storage_adaptor : detail::storage_reset<T> {
|
||||
storage_adaptor(const T& t) : base_type(t) {}
|
||||
storage_adaptor(T&& t) : base_type(std::move(t)) {}
|
||||
|
||||
template <typename U>
|
||||
storage_adaptor(const storage_adaptor<U>& rhs) {
|
||||
reset(rhs.size());
|
||||
template <typename U, typename = detail::requires_storage<U>>
|
||||
storage_adaptor(const U& rhs) {
|
||||
(*this) = rhs;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
storage_adaptor& operator=(const storage_adaptor<U>& rhs) {
|
||||
template <typename U, typename = detail::requires_storage<U>>
|
||||
storage_adaptor& operator=(const U& rhs) {
|
||||
reset(rhs.size());
|
||||
(*this) = rhs;
|
||||
for (std::size_t i = 0, n = this->size(); i < n; ++i) (*this)(i, rhs[i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -120,8 +119,8 @@ struct storage_adaptor : detail::storage_reset<T> {
|
||||
}
|
||||
|
||||
// precondition: storages have equal size
|
||||
template <typename U>
|
||||
storage_adaptor& operator+=(const storage_adaptor<U>& u) {
|
||||
template <typename U, typename = detail::requires_storage<U>>
|
||||
storage_adaptor& operator+=(const U& u) {
|
||||
const auto n = this->size();
|
||||
BOOST_ASSERT_MSG(n == u.size(), "sizes must be equal");
|
||||
for (std::size_t i = 0; i < n; ++i) (*this)(i, u[i]);
|
||||
@ -135,8 +134,8 @@ struct storage_adaptor : detail::storage_reset<T> {
|
||||
|
||||
storage_adaptor& operator/=(const double x) { return operator*=(1.0 / x); }
|
||||
|
||||
template <typename U>
|
||||
bool operator==(const storage_adaptor<U>& u) const {
|
||||
template <typename U, typename = detail::requires_storage<U>>
|
||||
bool operator==(const U& u) const {
|
||||
const auto n = this->size();
|
||||
if (n != u.size()) return false;
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
@ -144,17 +143,6 @@ struct storage_adaptor : detail::storage_reset<T> {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
struct storage_adaptor<adaptive_storage<A>> : adaptive_storage<A> {
|
||||
using base_type = adaptive_storage<A>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using const_reference = typename base_type::const_reference;
|
||||
using base_type::base_type;
|
||||
|
||||
storage_adaptor(const adaptive_storage<A>& t) : base_type(t) {}
|
||||
storage_adaptor(adaptive_storage<A>&& t) : base_type(std::move(t)) {}
|
||||
};
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace bh = boost::histogram;
|
||||
using adaptive_storage_type = bh::storage_adaptor<bh::adaptive_storage<>>;
|
||||
using adaptive_storage_type = bh::adaptive_storage<>;
|
||||
template <typename T>
|
||||
using array_storage = bh::storage_adaptor<std::vector<T>>;
|
||||
using bh::weight;
|
||||
|
@ -5,11 +5,11 @@
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram/adaptive_storage.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/literals.hpp>
|
||||
#include <boost/histogram/ostream_operators.hpp>
|
||||
#include <boost/histogram/storage/adaptive_storage.hpp>
|
||||
#include <boost/histogram/storage/array_storage.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include "utility.hpp"
|
||||
|
||||
using namespace boost::histogram;
|
||||
@ -19,7 +19,7 @@ void run_tests() {
|
||||
// compare
|
||||
{
|
||||
auto a = make(T1{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2));
|
||||
auto b = make_s(T2{}, array_storage<unsigned>(), axis::regular<>{3, 0, 3},
|
||||
auto b = make_s(T2{}, std::vector<unsigned>(), axis::regular<>{3, 0, 3},
|
||||
axis::integer<>(0, 2));
|
||||
BOOST_TEST_EQ(a, b);
|
||||
auto b2 = make(T2{}, axis::integer<>{0, 3}, axis::integer<>(0, 2));
|
||||
@ -46,7 +46,7 @@ void run_tests() {
|
||||
// copy_assign
|
||||
{
|
||||
auto a = make(T1{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2));
|
||||
auto b = make_s(T2{}, array_storage<unsigned>(), axis::regular<>{3, 0, 3},
|
||||
auto b = make_s(T2{}, std::vector<unsigned>(), axis::regular<>{3, 0, 3},
|
||||
axis::integer<>(0, 2));
|
||||
a(1, 1);
|
||||
BOOST_TEST_NE(a, b);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <array>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/histogram/adaptive_storage.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
@ -135,6 +136,28 @@ int main() {
|
||||
BOOST_TEST_TRAIT_FALSE((has_method_clear<D>));
|
||||
}
|
||||
|
||||
// has_allocator
|
||||
{
|
||||
struct A {};
|
||||
using B = std::vector<int>;
|
||||
using C = std::map<int, int>;
|
||||
using D = std::array<int, 10>;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((has_method_clear<A>));
|
||||
BOOST_TEST_TRAIT_TRUE((has_method_clear<B>));
|
||||
BOOST_TEST_TRAIT_TRUE((has_method_clear<C>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_method_clear<D>));
|
||||
}
|
||||
|
||||
// is_storage
|
||||
{
|
||||
struct A {};
|
||||
using B = bh::adaptive_storage<>;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_storage<A>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_storage<B>));
|
||||
}
|
||||
|
||||
// is_indexable
|
||||
{
|
||||
struct A {};
|
||||
|
@ -18,7 +18,7 @@ using namespace boost::histogram;
|
||||
template <typename T>
|
||||
using vector_storage = storage_adaptor<std::vector<T>>;
|
||||
template <typename T>
|
||||
using array_storage = storage_adaptor<std::array<100, T>>;
|
||||
using array_storage = storage_adaptor<std::array<T, 100>>;
|
||||
|
||||
int main() {
|
||||
// ctor, copy, move
|
||||
@ -47,13 +47,13 @@ int main() {
|
||||
vector_storage<unsigned char> c, d;
|
||||
c.reset(1);
|
||||
d.reset(2);
|
||||
a.increment(0);
|
||||
b.increment(0);
|
||||
c.increment(0);
|
||||
c.increment(0);
|
||||
d.increment(0);
|
||||
d.add(1, 5);
|
||||
d.add(0, 2);
|
||||
a(0);
|
||||
b(0);
|
||||
c(0);
|
||||
c(0);
|
||||
d(0);
|
||||
d(1, 5);
|
||||
d(0, 2);
|
||||
BOOST_TEST_EQ(a[0], 1);
|
||||
BOOST_TEST_EQ(b[0], 1);
|
||||
BOOST_TEST_EQ(c[0], 2);
|
||||
@ -69,11 +69,11 @@ int main() {
|
||||
{
|
||||
vector_storage<double> a;
|
||||
a.reset(2);
|
||||
a.increment(0);
|
||||
a(0);
|
||||
a *= 3;
|
||||
BOOST_TEST_EQ(a[0], 3);
|
||||
BOOST_TEST_EQ(a[1], 0);
|
||||
a.add(1, 2);
|
||||
a(1, 2);
|
||||
BOOST_TEST_EQ(a[0], 3);
|
||||
BOOST_TEST_EQ(a[1], 2);
|
||||
a *= 3;
|
||||
@ -85,7 +85,7 @@ int main() {
|
||||
{
|
||||
vector_storage<unsigned> a;
|
||||
a.reset(1);
|
||||
a.increment(0);
|
||||
a(0);
|
||||
decltype(a) b;
|
||||
b.reset(2);
|
||||
BOOST_TEST(!(a == b));
|
||||
@ -112,7 +112,7 @@ int main() {
|
||||
{
|
||||
vector_storage<unsigned> a;
|
||||
a.reset(1);
|
||||
a.increment(0);
|
||||
a(0);
|
||||
decltype(a) b;
|
||||
BOOST_TEST(!(a == b));
|
||||
b = std::move(a);
|
||||
@ -129,12 +129,12 @@ int main() {
|
||||
{
|
||||
vector_storage<weight_counter<double>> a;
|
||||
a.reset(1);
|
||||
a.increment(0);
|
||||
a.add(0, 1);
|
||||
a.add(0, weight_counter<double>(1, 0));
|
||||
a(0);
|
||||
a(0, 1);
|
||||
a(0, weight_counter<double>(1, 0));
|
||||
BOOST_TEST_EQ(a[0].value(), 3);
|
||||
BOOST_TEST_EQ(a[0].variance(), 2);
|
||||
a.add(0, weight(2));
|
||||
a(0, weight(2));
|
||||
BOOST_TEST_EQ(a[0].value(), 5);
|
||||
BOOST_TEST_EQ(a[0].variance(), 6);
|
||||
}
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
using i0 = boost::mp11::mp_size_t<0>;
|
||||
using i1 = boost::mp11::mp_size_t<1>;
|
||||
@ -52,8 +52,7 @@ auto sum(const Histogram& h) {
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
std::vector<axis::variant<detail::unqual<Ts>...>>
|
||||
make_axis_vector(Ts&& ... ts) {
|
||||
std::vector<axis::variant<detail::unqual<Ts>...>> make_axis_vector(Ts&&... ts) {
|
||||
using T = axis::variant<detail::unqual<Ts>...>;
|
||||
return std::vector<T>({T(std::forward<Ts>(ts))...});
|
||||
}
|
||||
@ -85,10 +84,8 @@ auto make_s(dynamic_tag, S&& s, Axes&&... axes)
|
||||
return make_histogram_with(s, make_axis_vector(std::forward<Axes>(axes)...));
|
||||
}
|
||||
|
||||
using tracing_allocator_db = std::unordered_map<
|
||||
std::type_index,
|
||||
std::pair<std::size_t, std::size_t>
|
||||
>;
|
||||
using tracing_allocator_db =
|
||||
std::unordered_map<std::type_index, std::pair<std::size_t, std::size_t>>;
|
||||
|
||||
template <class T>
|
||||
struct tracing_allocator {
|
||||
@ -99,21 +96,16 @@ struct tracing_allocator {
|
||||
tracing_allocator() noexcept {}
|
||||
tracing_allocator(tracing_allocator_db& x) noexcept : db(&x) {}
|
||||
template <class U>
|
||||
tracing_allocator(const tracing_allocator<U>& a) noexcept
|
||||
: db(a.db) {}
|
||||
tracing_allocator(const tracing_allocator<U>& a) noexcept : db(a.db) {}
|
||||
~tracing_allocator() noexcept {}
|
||||
|
||||
T* allocate(std::size_t n) {
|
||||
if (db) {
|
||||
(*db)[typeid(T)].first += n;
|
||||
}
|
||||
if (db) { (*db)[typeid(T)].first += n; }
|
||||
return static_cast<T*>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n) {
|
||||
if (db) {
|
||||
(*db)[typeid(T)].second += n;
|
||||
}
|
||||
if (db) { (*db)[typeid(T)].second += n; }
|
||||
::operator delete((void*)p);
|
||||
}
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram/ostream_operators.hpp>
|
||||
#include <boost/histogram/storage/weight_counter.hpp>
|
||||
#include <boost/histogram/weight_counter.hpp>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user