wip: growing axis for axis::integer

This commit is contained in:
Hans Dembinski 2019-01-13 22:14:53 +01:00
parent 0479c512e3
commit 8e9dd85837
15 changed files with 247 additions and 110 deletions

View File

@ -93,6 +93,7 @@ compiled_test(test/axis_category_test.cpp)
compiled_test(test/axis_integer_test.cpp)
compiled_test(test/axis_option_test.cpp)
compiled_test(test/axis_regular_test.cpp)
compiled_test(test/axis_traits_test.cpp)
compiled_test(test/axis_variable_test.cpp)
compiled_test(test/axis_variant_test.cpp)
compiled_test(test/detail_test.cpp)

View File

@ -7,6 +7,7 @@
#ifndef BOOST_HISTOGRAM_AXIS_BASE_HPP
#define BOOST_HISTOGRAM_AXIS_BASE_HPP
#include <boost/assert.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/compressed_pair.hpp>
#include <boost/histogram/detail/meta.hpp>
@ -29,7 +30,7 @@ public:
/// Returns the number of bins, without extra bins.
int size() const noexcept { return size_meta_.first(); }
/// Returns the options.
constexpr option options() const noexcept { return Options; }
static constexpr option options() noexcept { return Options; }
/// Returns the metadata.
metadata_type& metadata() noexcept { return size_meta_.second(); }
/// Returns the metadata (const version).
@ -45,6 +46,8 @@ public:
void serialize(Archive&, unsigned);
protected:
base() = default;
base(unsigned n, metadata_type m) : size_meta_(n, std::move(m)) {
if (size() == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
const auto max_index = std::numeric_limits<int>::max() -
@ -55,14 +58,17 @@ protected:
std::invalid_argument(detail::cat("bins <= ", max_index, " required")));
}
base() : size_meta_(0) {}
bool operator==(const base& rhs) const noexcept {
return size() == rhs.size() && detail::relaxed_equal(metadata(), rhs.metadata());
}
void grow(int n) {
BOOST_ASSERT(n > 0);
size_meta_.first() += n;
}
private:
detail::compressed_pair<int, metadata_type> size_meta_;
detail::compressed_pair<int, metadata_type> size_meta_{0};
};
} // namespace axis

View File

@ -17,6 +17,7 @@
#include <limits>
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace boost {
namespace histogram {
@ -29,17 +30,22 @@ namespace axis {
template <typename IntType, typename MetaData, option Options>
class integer : public base<MetaData, Options>,
public iterator_mixin<integer<IntType, MetaData, Options>> {
using base_type = base<MetaData, Options>;
using value_type = IntType;
using metadata_type = MetaData;
using index_type = std::conditional_t<std::is_integral<value_type>::value, int, double>;
static_assert(!test(Options, option::circular) || !test(Options, option::underflow),
"circular axis cannot have underflow");
static_assert(!std::is_integral<IntType>::value || std::is_same<IntType, int>::value,
"integer axis requires type floating point type or int");
using base_type = base<MetaData, Options>;
public:
using metadata_type = MetaData;
using value_type = IntType;
private:
using index_type = std::conditional_t<std::is_integral<value_type>::value, int, double>;
public:
integer() = default;
/** Construct over semi-open integer interval [start, stop).
*
* \param start first integer of covered range.
@ -61,13 +67,16 @@ public:
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
}
integer() = default;
/// Returns the bin index for the passed argument.
int operator()(value_type x) const noexcept {
return index_impl(std::is_floating_point<value_type>(), x);
}
template <option O = Options, class = std::enable_if_t<test(O, option::growth)>>
auto update(value_type x) {
return update_impl(std::is_floating_point<value_type>(), x);
}
/// Returns axis value for index.
value_type value(index_type i) const noexcept {
if (!test(Options, option::circular)) {
@ -90,19 +99,18 @@ public:
template <class Archive>
void serialize(Archive&, unsigned);
private:
protected:
int index_impl(std::false_type, int x) const noexcept {
const auto z = x - min_;
if (test(Options, option::circular)) {
return z - std::floor(double(z) / base_type::size()) * base_type::size();
} else if (z < base_type::size()) {
return z >= 0 ? z : -1;
}
if (test(Options, option::circular))
return z - std::floor(float(z) / base_type::size()) * base_type::size();
if (z < base_type::size()) return z >= 0 ? z : -1;
return base_type::size();
}
template <typename T>
int index_impl(std::true_type, T x) const noexcept {
// need to handle NaN, cannot simply cast to int and call int-implementation
const auto z = std::floor(x - min_);
if (test(Options, option::circular)) {
if (std::isfinite(z))
@ -114,6 +122,27 @@ private:
return base_type::size();
}
auto update_impl(std::false_type, int x) noexcept {
const auto i = x - min_;
if (i >= 0) {
if (i < base_type::size()) return std::make_pair(i, 0);
const auto n = i - base_type::size() + 1;
base_type::grow(n);
return std::make_pair(i, -n);
}
min_ += i;
base_type::grow(-i);
return std::make_pair(0, -i);
}
template <class T>
auto update_impl(std::true_type, T x) {
if (std::isfinite(x))
return update_impl(std::false_type{}, static_cast<int>(std::floor(x)));
BOOST_THROW_EXCEPTION(std::invalid_argument("argument is not finite"));
return std::make_pair(0, 0);
}
decltype(auto) subscript_impl(std::true_type, int idx) const noexcept {
return interval_view<integer>(*this, idx);
}
@ -122,7 +151,7 @@ private:
return value(idx);
}
value_type min_ = 0;
int min_ = 0;
};
#if __cpp_deduction_guides >= 201606

View File

@ -17,6 +17,7 @@
#include <cmath>
#include <limits>
#include <stdexcept>
#include <utility>
namespace boost {
namespace histogram {
@ -85,19 +86,22 @@ struct pow {
* The most common binning strategy.
* Very fast. Binning is a O(1) operation.
*/
template <typename RealType, typename Transform, typename MetaData, option Options>
template <class RealType, class Transform, class MetaData, option Options>
class regular : public base<MetaData, Options>,
public iterator_mixin<regular<RealType, Transform, MetaData, Options>>,
protected Transform {
using base_type = base<MetaData, Options>;
using metadata_type = MetaData;
using transform_type = Transform;
using value_type = RealType;
using unit_type = detail::get_unit_type<value_type>;
using internal_type = detail::get_scale_type<value_type>;
static_assert(!test(Options, option::circular) || !test(Options, option::underflow),
"circular axis cannot have underflow");
using base_type = base<MetaData, Options>;
public:
using value_type = RealType;
using transform_type = Transform;
using metadata_type = MetaData;
private:
using unit_type = detail::get_unit_type<value_type>;
using internal_type = detail::get_scale_type<value_type>;
public:
/** Construct n bins over real transformed range [begin, end).
@ -167,6 +171,32 @@ public:
return base_type::size(); // also returned if x is NaN
}
// /// Returns index and shift (if axis has grown) for the passed argument.
// template <option O = Options, class = std::enable_if_t<test(O, option::growth)>>
// auto update(value_type x) {
// auto z = (this->forward(x / unit_type()) - min_) / delta_;
// if (std::isfinite(z)) {
// if (0 <= z) {
// if (z < 1) return std::make_pair(static_cast<int>(z * base_type::size()), 0);
// const auto i = static_cast<int>(z * base_type::size());
// const auto shift = i - base_type::size() + 1;
// delta_ /= base_type::size();
// base_type::grow(shift);
// delta_ *= base_type::size();
// return std::make_pair(i, shift);
// }
// z = std::floor(z);
// const auto i = static_cast<int>(z * base_type::size());
// min_ += delta_ * z;
// delta_ /= base_type::size();
// base_type::grow(-i);
// delta_ *= base_type::size();
// return std::make_pair(0, i);
// }
// BOOST_THROW_EXCEPTION(std::invalid_argument("argument is not finite"));
// return std::make_pair(0, 0);
// }
/// Returns axis value for fractional index.
value_type value(double i) const noexcept {
auto z = i / base_type::size();
@ -198,7 +228,7 @@ public:
private:
internal_type min_, delta_;
}; // namespace axis
};
#if __cpp_deduction_guides >= 201606

View File

@ -19,6 +19,16 @@ namespace boost {
namespace histogram {
namespace detail {
template <class T>
constexpr axis::option options_impl(std::true_type, const T& t) noexcept {
return t.options();
}
template <class T>
constexpr axis::option options_impl(std::false_type, const T&) noexcept {
return axis::option::none;
}
template <class FIntArg, class FDoubleArg, class T>
decltype(auto) value_method_switch(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
return static_if<has_method_value<T>>(
@ -68,10 +78,8 @@ decltype(auto) metadata(T&& t) noexcept {
}
template <class T>
option options(const T& axis) noexcept {
return detail::static_if<detail::has_method_options<T>>(
[](const auto& a) { return a.options(); },
[](const T&) { return axis::option::none; }, axis);
constexpr option options(const T& t) noexcept {
return detail::options_impl(detail::has_method_options<T>(), t);
}
template <class T>

View File

@ -71,4 +71,4 @@ using compressed_pair =
} // namespace histogram
} // namespace boost
#endif
#endif

View File

@ -120,7 +120,7 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
for (const auto& x : storage) {
auto ns = new_storage.begin();
sit = shifts.begin();
for (const auto& d : data) { ns += (d.idx - std::min(*sit++, 0)) * d.stride; }
for (const auto& d : data) { ns += (d.idx + std::max(*sit++, 0)) * d.stride; }
auto dit = data.begin();
const auto last = data.end() - 1;
++dit->idx;
@ -168,7 +168,7 @@ optional_index args_to_index(std::false_type, S&, T& axes, const U& args) {
template <unsigned I, unsigned N, class S, class T, class U>
optional_index args_to_index(std::true_type, S& storage, T& axes, const U& args) {
optional_index idx;
auto shifts = make_stack_buffer<int>(axes, 0);
auto shifts = make_stack_buffer<int>(axes);
const auto rank = get_size(axes);
if (rank == 1 && N > 1)
linearize_value(idx, shifts[0], axis_get<0>(axes), tuple_slice<I, N>(args));

View File

@ -174,7 +174,9 @@ BOOST_HISTOGRAM_MAKE_SFINAE(has_method_lower, &T::lower);
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_value, &T::value);
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_update, &T::update);
BOOST_HISTOGRAM_MAKE_SFINAE(
has_method_update,
(std::declval<T>().update(std::declval<typename T::value_type&>())));
template <typename T>
using get_value_method_return_type_impl = decltype(std::declval<T&>().value(0));
@ -184,7 +186,7 @@ using has_method_value_with_convertible_return_type =
typename std::is_convertible<mp_eval_or<get_value_method_return_type_impl, T, void>,
R>::type;
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_options, (std::declval<const T&>().options()));
BOOST_HISTOGRAM_MAKE_SFINAE(has_method_options, (&T::options));
BOOST_HISTOGRAM_MAKE_SFINAE(has_allocator, &T::get_allocator);

View File

@ -90,12 +90,30 @@ int main() {
BOOST_TEST_EQ(a(std::numeric_limits<double>::quiet_NaN()), 2);
}
// axis::integer with growth
{
axis::integer<double, axis::null_type, axis::option::growth> a;
BOOST_TEST_EQ(a.size(), 0);
BOOST_TEST_EQ(a.update(0), std::make_pair(0, -1));
BOOST_TEST_EQ(a.size(), 1);
BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
BOOST_TEST_EQ(a.size(), 2);
BOOST_TEST_EQ(a.update(-1), std::make_pair(0, 1));
BOOST_TEST_EQ(a.size(), 3);
BOOST_TEST_THROWS(a.update(std::numeric_limits<double>::infinity()),
std::invalid_argument);
BOOST_TEST_THROWS(a.update(-std::numeric_limits<double>::infinity()),
std::invalid_argument);
BOOST_TEST_THROWS(a.update(std::numeric_limits<double>::quiet_NaN()),
std::invalid_argument);
}
// iterators
{
test_axis_iterator(axis::integer<int>(0, 4), 0, 4);
test_axis_iterator(axis::integer<double>(0, 4), 0, 4);
test_axis_iterator(
axis::integer<int, axis::null_type, axis::option::circular>(0, 4), 0, 4);
test_axis_iterator(axis::integer<int, axis::null_type, axis::option::circular>(0, 4),
0, 4);
}
// shrink and rebin

View File

@ -124,12 +124,30 @@ int main() {
BOOST_TEST_EQ(a(std::numeric_limits<double>::quiet_NaN()), 4);
}
// axis::regular with growth
// {
// axis::regular<double, tr::id, axis::null_type, axis::option::growth> a{1, 0, 1};
// BOOST_TEST_EQ(a.size(), 1);
// BOOST_TEST_EQ(a.update(0), std::make_pair(0, 0));
// BOOST_TEST_EQ(a.size(), 1);
// BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
// BOOST_TEST_EQ(a.size(), 2);
// BOOST_TEST_EQ(a.update(-1), std::make_pair(0, 1));
// BOOST_TEST_EQ(a.size(), 3);
// BOOST_TEST_THROWS(a(std::numeric_limits<double>::infinity()),
// std::invalid_argument);
// BOOST_TEST_THROWS(a(-std::numeric_limits<double>::infinity()),
// std::invalid_argument);
// BOOST_TEST_THROWS(a(std::numeric_limits<double>::quiet_NaN()),
// std::invalid_argument);
// }
// iterators
{
test_axis_iterator(axis::regular<>(5, 0, 1), 0, 5);
test_axis_iterator(
axis::regular<double, tr::id, axis::null_type, axis::option::none>(5, 0, 1),
0, 5);
axis::regular<double, tr::id, axis::null_type, axis::option::none>(5, 0, 1), 0,
5);
test_axis_iterator(axis::circular<>(5, 0, 1), 0, 5);
}

30
test/axis_traits_test.cpp Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2018 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)
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/axis/integer.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/mp11.hpp>
#include "utility_axis.hpp"
using namespace boost::histogram;
int main() {
{
auto a = axis::integer<>();
using B =
boost::mp11::mp_bool<axis::test(axis::traits::options(a), axis::option::growth)>;
BOOST_TEST_NOT(B::value);
}
{
auto a = axis::integer<int, axis::null_type, axis::option::growth>();
using B =
boost::mp11::mp_bool<axis::test(axis::traits::options(a), axis::option::growth)>;
BOOST_TEST_EQ(B::value, true);
}
return boost::report_errors();
}

View File

@ -14,29 +14,11 @@
using namespace boost::histogram;
struct regular {
int operator()(int x) const { return x - min_; }
auto update(int x) {
const auto i = (*this)(x);
if (i >= 0) {
if (i < size_) return std::make_pair(i, 0);
const auto off = i - size_ + 1;
size_ += off;
return std::make_pair(i, off);
}
min_ += i;
size_ -= i;
return std::make_pair(0, i);
}
int size() const { return size_; }
int min_ = 0;
int size_ = 1;
};
using integer = axis::integer<int, axis::null_type, axis::option::growth>;
struct category {
using value_type = std::string;
int operator()(const std::string& x) const {
auto it = set_.find(x);
if (it != set_.end()) return it->second;
@ -47,7 +29,7 @@ struct category {
const auto i = (*this)(x);
if (i < size()) return std::make_pair(i, 0);
set_.emplace(x, i);
return std::make_pair(i, 1);
return std::make_pair(i, -1);
}
int size() const { return static_cast<int>(set_.size()); }
@ -58,20 +40,22 @@ struct category {
template <typename Tag>
void run_tests() {
{
auto h = make_s(Tag(), std::vector<int>(), regular());
auto h = make_s(Tag(), std::vector<int>(), integer());
const auto& a = h.axis();
BOOST_TEST_EQ(h.size(), 0);
BOOST_TEST_EQ(a.size(), 0);
h(0);
BOOST_TEST_EQ(h.size(), 1);
BOOST_TEST_EQ(h[0], 1);
h(2);
BOOST_TEST_EQ(h.size(), 3);
BOOST_TEST_EQ(h.axis(0).size(), 3);
BOOST_TEST_EQ(a.size(), 3);
BOOST_TEST_EQ(h[0], 1);
BOOST_TEST_EQ(h[1], 0);
BOOST_TEST_EQ(h[2], 1);
h(-2);
BOOST_TEST_EQ(h.size(), 5);
BOOST_TEST_EQ(a.size(), 5);
BOOST_TEST_EQ(h[0], 1);
BOOST_TEST_EQ(h[1], 0);
BOOST_TEST_EQ(h[2], 1);
@ -80,13 +64,15 @@ void run_tests() {
}
{
auto h = make_s(Tag(), std::vector<int>(), regular(), category());
auto h = make_s(Tag(), std::vector<int>(), integer(), category());
const auto& a = h.axis(0);
const auto& b = h.axis(1);
BOOST_TEST_EQ(a.size(), 1);
BOOST_TEST_EQ(a.size(), 0);
BOOST_TEST_EQ(b.size(), 0);
BOOST_TEST_EQ(h.size(), 0);
h(0, "x");
BOOST_TEST_EQ(a.size(), 1);
BOOST_TEST_EQ(b.size(), 1);
BOOST_TEST_EQ(h.size(), 1);
h(2, "x");
BOOST_TEST_EQ(h.size(), 3);
@ -104,33 +90,21 @@ void run_tests() {
}
int main() {
{
regular a;
BOOST_TEST_EQ(a.update(0), std::make_pair(0, 0));
BOOST_TEST_EQ(a.size(), 1);
BOOST_TEST_EQ(a.update(2), std::make_pair(2, 2));
BOOST_TEST_EQ(a.size(), 3);
BOOST_TEST_EQ(a.update(2), std::make_pair(2, 0));
BOOST_TEST_EQ(a.size(), 3);
BOOST_TEST_EQ(a.update(-2), std::make_pair(0, -2));
BOOST_TEST_EQ(a.size(), 5);
}
{
category a;
BOOST_TEST_EQ(a.size(), 0);
BOOST_TEST_EQ(a.update("x"), std::make_pair(0, 1));
BOOST_TEST_EQ(a.update("x"), std::make_pair(0, -1));
BOOST_TEST_EQ(a.size(), 1);
BOOST_TEST_EQ(a.update("y"), std::make_pair(1, 1));
BOOST_TEST_EQ(a.update("y"), std::make_pair(1, -1));
BOOST_TEST_EQ(a.size(), 2);
BOOST_TEST_EQ(a.update("y"), std::make_pair(1, 0));
BOOST_TEST_EQ(a.size(), 2);
BOOST_TEST_EQ(a.update("z"), std::make_pair(2, 1));
BOOST_TEST_EQ(a.update("z"), std::make_pair(2, -1));
BOOST_TEST_EQ(a.size(), 3);
}
run_tests<static_tag>();
run_tests<dynamic_tag>();
// run_tests<dynamic_tag>();
return boost::report_errors();
}

View File

@ -17,7 +17,8 @@
using namespace boost::histogram;
struct growing_axis {
auto update(int) { return std::make_pair(0, 0); }
using value_type = int;
auto update(value_type) { return std::make_pair(0, 0); }
};
int main() {

View File

@ -12,7 +12,6 @@
#include <boost/histogram/axis/regular.hpp>
#include <boost/histogram/axis/variant.hpp>
#include <boost/histogram/detail/meta.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/histogram/sample.hpp>
#include <boost/histogram/weight.hpp>
#include <deque>
@ -26,15 +25,21 @@
#include "utility_allocator.hpp"
#include "utility_meta.hpp"
namespace bh = boost::histogram;
using namespace bh::detail;
using namespace bh::literals;
using namespace boost::histogram;
using namespace boost::histogram::detail;
struct VisitorTestFunctor {
template <typename T>
T operator()(T&&);
};
template <bool B>
struct OptionalUpdate {
using value_type = int;
template <bool BB = B, class = std::enable_if_t<BB>>
void update(value_type) {}
};
int main() {
// has_method_value*
{
@ -63,13 +68,9 @@ int main() {
struct B {
void options() {}
};
struct C {
bh::axis::option options() const { return {}; }
};
BOOST_TEST_TRAIT_FALSE((has_method_options<A>));
BOOST_TEST_TRAIT_FALSE((has_method_options<B>));
BOOST_TEST_TRAIT_TRUE((has_method_options<C>));
BOOST_TEST_TRAIT_TRUE((has_method_options<B>));
}
// has_method_metadata
@ -83,6 +84,24 @@ int main() {
BOOST_TEST_TRAIT_TRUE((has_method_metadata<B>));
}
// has_method_update
{
struct A {};
struct B {
using value_type = int;
void update(value_type) {}
};
using C = axis::integer<int, axis::null_type, axis::option::defaults>;
using D = axis::integer<int, axis::null_type, axis::option::growth>;
BOOST_TEST_TRAIT_FALSE((has_method_update<A>));
BOOST_TEST_TRAIT_TRUE((has_method_update<B>));
BOOST_TEST_TRAIT_FALSE((has_method_update<OptionalUpdate<false>>));
BOOST_TEST_TRAIT_TRUE((has_method_update<OptionalUpdate<true>>));
BOOST_TEST_TRAIT_FALSE((has_method_update<C>));
BOOST_TEST_TRAIT_TRUE((has_method_update<D>));
}
// has_method_resize
{
struct A {};
@ -134,7 +153,7 @@ int main() {
// is_storage
{
struct A {};
using B = bh::adaptive_storage<>;
using B = adaptive_storage<>;
BOOST_TEST_TRAIT_FALSE((is_storage<A>));
BOOST_TEST_TRAIT_TRUE((is_storage<B>));
@ -218,7 +237,7 @@ int main() {
struct D {
int size();
};
using E = bh::axis::variant<bh::axis::regular<>>;
using E = axis::variant<axis::regular<>>;
BOOST_TEST_TRAIT_FALSE((is_axis<A>));
BOOST_TEST_TRAIT_TRUE((is_axis<B>));
@ -250,8 +269,8 @@ int main() {
{
struct A {};
BOOST_TEST_TRAIT_FALSE((is_axis_variant<A>));
BOOST_TEST_TRAIT_TRUE((is_axis_variant<bh::axis::variant<>>));
BOOST_TEST_TRAIT_TRUE((is_axis_variant<bh::axis::variant<bh::axis::regular<>>>));
BOOST_TEST_TRAIT_TRUE((is_axis_variant<axis::variant<>>));
BOOST_TEST_TRAIT_TRUE((is_axis_variant<axis::variant<axis::regular<>>>));
}
// naked
@ -304,9 +323,9 @@ int main() {
// visitor_return_type
{
using V1 = bh::axis::variant<char>;
using V2 = bh::axis::variant<int>&;
using V3 = const bh::axis::variant<long>&;
using V1 = axis::variant<char>;
using V2 = axis::variant<int>&;
using V3 = const axis::variant<long>&;
BOOST_TEST_TRAIT_TRUE(
(std::is_same<visitor_return_type<VisitorTestFunctor, V1>, char>));
BOOST_TEST_TRAIT_TRUE(
@ -338,10 +357,10 @@ int main() {
// is_sequence_of_axis
{
using A = std::vector<bh::axis::regular<>>;
using B = std::vector<bh::axis::variant<bh::axis::regular<>>>;
using A = std::vector<axis::regular<>>;
using B = std::vector<axis::variant<axis::regular<>>>;
using C = std::vector<int>;
auto v = std::vector<bh::axis::variant<bh::axis::regular<>, bh::axis::integer<>>>();
auto v = std::vector<axis::variant<axis::regular<>, axis::integer<>>>();
BOOST_TEST_TRAIT_TRUE((is_sequence_of_any_axis<A>));
BOOST_TEST_TRAIT_TRUE((is_sequence_of_axis<A>));
BOOST_TEST_TRAIT_FALSE((is_sequence_of_axis_variant<A>));
@ -356,7 +375,7 @@ int main() {
{
struct A {};
using B = int;
using C = decltype(bh::weight(1));
using C = decltype(weight(1));
BOOST_TEST_TRAIT_FALSE((is_weight<A>));
BOOST_TEST_TRAIT_FALSE((is_weight<B>));
BOOST_TEST_TRAIT_TRUE((is_weight<C>));
@ -366,8 +385,8 @@ int main() {
{
struct A {};
using B = int;
using C = decltype(bh::sample(1));
using D = decltype(bh::sample(1, 2.0));
using C = decltype(sample(1));
using D = decltype(sample(1, 2.0));
BOOST_TEST_TRAIT_FALSE((is_sample<A>));
BOOST_TEST_TRAIT_FALSE((is_sample<B>));
BOOST_TEST_TRAIT_TRUE((is_sample<C>));
@ -392,9 +411,9 @@ int main() {
struct A {};
auto a = make_default(A());
BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(a), A>));
bh::tracing_allocator_db db;
using B = std::vector<int, bh::tracing_allocator<int>>;
B b = make_default(B(bh::tracing_allocator<int>(db)));
tracing_allocator_db db;
using B = std::vector<int, tracing_allocator<int>>;
B b = make_default(B(tracing_allocator<int>(db)));
b.resize(100);
BOOST_TEST_EQ(db[&BOOST_CORE_TYPEID(int)].first, 100);
}

View File

@ -10,6 +10,7 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/axis/ostream_operators.hpp>
#include <boost/histogram/fwd.hpp>
#include "utility_meta.hpp"
namespace boost {
namespace histogram {