mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
wip: growing axis for axis::integer
This commit is contained in:
parent
0479c512e3
commit
8e9dd85837
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -71,4 +71,4 @@ using compressed_pair =
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
30
test/axis_traits_test.cpp
Normal 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();
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user