working version

This commit is contained in:
Hans Dembinski 2018-10-29 10:54:05 +01:00
parent a17a6c677c
commit 61be24b94d
10 changed files with 82 additions and 64 deletions

View File

@ -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;

View File

@ -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

View File

@ -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()));

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 {};

View File

@ -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);
}

View File

@ -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);
}
};

View File

@ -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>