add boost on mac
This commit is contained in:
16
macx64/include/boost/histogram/detail/attribute.hpp
Normal file
16
macx64/include/boost/histogram/detail/attribute.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_ATTRIBUTE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_ATTRIBUTE_HPP
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define BOOST_HISTOGRAM_DETAIL_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define BOOST_HISTOGRAM_DETAIL_NODISCARD
|
||||
#endif
|
||||
|
||||
#endif
|
||||
176
macx64/include/boost/histogram/detail/axes.hpp
Normal file
176
macx64/include/boost/histogram/detail/axes.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2015-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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_AXES_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_AXES_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <unsigned N, class... Ts>
|
||||
decltype(auto) axis_get(std::tuple<Ts...>& axes) {
|
||||
return std::get<N>(axes);
|
||||
}
|
||||
|
||||
template <unsigned N, class... Ts>
|
||||
decltype(auto) axis_get(const std::tuple<Ts...>& axes) {
|
||||
return std::get<N>(axes);
|
||||
}
|
||||
|
||||
template <unsigned N, class T>
|
||||
decltype(auto) axis_get(T& axes) {
|
||||
return axes[N];
|
||||
}
|
||||
|
||||
template <unsigned N, class T>
|
||||
decltype(auto) axis_get(const T& axes) {
|
||||
return axes[N];
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
decltype(auto) axis_get(std::tuple<Ts...>& axes, unsigned i) {
|
||||
return mp11::mp_with_index<sizeof...(Ts)>(
|
||||
i, [&](auto I) { return axis::variant<Ts&...>(std::get<I>(axes)); });
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
decltype(auto) axis_get(const std::tuple<Ts...>& axes, unsigned i) {
|
||||
return mp11::mp_with_index<sizeof...(Ts)>(
|
||||
i, [&](auto I) { return axis::variant<const Ts&...>(std::get<I>(axes)); });
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) axis_get(T& axes, unsigned i) {
|
||||
return axes.at(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) axis_get(const T& axes, unsigned i) {
|
||||
return axes.at(i);
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
bool axes_equal(const std::tuple<Ts...>& ts, const std::tuple<Us...>& us) {
|
||||
return static_if<std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>>(
|
||||
[](const auto& ts, const auto& us) {
|
||||
using N = mp11::mp_size<remove_cvref_t<decltype(ts)>>;
|
||||
bool equal = true;
|
||||
mp11::mp_for_each<mp11::mp_iota<N>>(
|
||||
[&](auto I) { equal &= relaxed_equal(std::get<I>(ts), std::get<I>(us)); });
|
||||
return equal;
|
||||
},
|
||||
[](const auto&, const auto&) { return false; }, ts, us);
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
bool axes_equal(const std::tuple<Ts...>& t, const U& u) {
|
||||
if (sizeof...(Ts) != u.size()) return false;
|
||||
bool equal = true;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>(
|
||||
[&](auto I) { equal &= u[I] == std::get<I>(t); });
|
||||
return equal;
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
bool axes_equal(const T& t, const std::tuple<Us...>& u) {
|
||||
return axes_equal(u, t);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool axes_equal(const T& t, const U& u) {
|
||||
if (t.size() != u.size()) return false;
|
||||
return std::equal(t.begin(), t.end(), u.begin());
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
void axes_assign(std::tuple<Ts...>& t, const std::tuple<Us...>& u) {
|
||||
static_if<std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>>(
|
||||
[](auto& a, const auto& b) { a = b; },
|
||||
[](auto&, const auto&) {
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("cannot assign axes, types do not match"));
|
||||
},
|
||||
t, u);
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
void axes_assign(std::tuple<Ts...>& t, const U& u) {
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>([&](auto I) {
|
||||
using T = mp11::mp_at_c<std::tuple<Ts...>, I>;
|
||||
std::get<I>(t) = axis::get<T>(u[I]);
|
||||
});
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
void axes_assign(T& t, const std::tuple<Us...>& u) {
|
||||
// resize instead of reserve, because t may not be empty and we want exact capacity
|
||||
t.resize(sizeof...(Us));
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>(
|
||||
[&](auto I) { t[I] = std::get<I>(u); });
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void axes_assign(T& t, const U& u) {
|
||||
t.assign(u.begin(), u.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void axis_index_is_valid(const T& axes, const unsigned N) {
|
||||
BOOST_ASSERT_MSG(N < get_size(axes), "index out of range");
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis_impl(std::true_type, const T& axes, F&& f) {
|
||||
for (const auto& x : axes) { axis::visit(std::forward<F>(f), x); }
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis_impl(std::false_type, const T& axes, F&& f) {
|
||||
for (const auto& x : axes) std::forward<F>(f)(x);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis(const T& axes, F&& f) {
|
||||
using U = mp11::mp_first<T>;
|
||||
for_each_axis_impl(is_axis_variant<U>(), axes, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename F, typename... Ts>
|
||||
void for_each_axis(const std::tuple<Ts...>& axes, F&& f) {
|
||||
mp11::tuple_for_each(axes, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t bincount(const T& axes) {
|
||||
std::size_t n = 1;
|
||||
for_each_axis(axes, [&n](const auto& a) {
|
||||
const auto old = n;
|
||||
const auto s = axis::traits::extent(a);
|
||||
n *= s;
|
||||
if (s > 0 && n < old) BOOST_THROW_EXCEPTION(std::overflow_error("bincount overflow"));
|
||||
});
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
34
macx64/include/boost/histogram/detail/cat.hpp
Normal file
34
macx64/include/boost/histogram/detail/cat.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2015-2017 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_CAT_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_CAT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
BOOST_ATTRIBUTE_UNUSED inline void cat_impl(std::ostringstream&) {}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
void cat_impl(std::ostringstream& os, const T& t, const Ts&... ts) {
|
||||
os << t;
|
||||
cat_impl(os, ts...);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
std::string cat(const Ts&... args) {
|
||||
std::ostringstream os;
|
||||
cat_impl(os, args...);
|
||||
return os.str();
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
78
macx64/include/boost/histogram/detail/common_type.hpp
Normal file
78
macx64/include/boost/histogram/detail/common_type.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2015-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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
|
||||
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
// clang-format off
|
||||
template <class T, class U>
|
||||
using common_axes = mp11::mp_cond<
|
||||
is_tuple<T>, T,
|
||||
is_tuple<U>, U,
|
||||
is_sequence_of_axis<T>, T,
|
||||
is_sequence_of_axis<U>, U,
|
||||
std::true_type, T
|
||||
>;
|
||||
|
||||
template <class T, class U>
|
||||
using common_container = mp11::mp_cond<
|
||||
is_array_like<T>, T,
|
||||
is_array_like<U>, U,
|
||||
is_vector_like<T>, T,
|
||||
is_vector_like<U>, U,
|
||||
std::true_type, T
|
||||
>;
|
||||
// clang-format on
|
||||
|
||||
template <class T>
|
||||
using type_score = mp11::mp_size_t<((!std::is_pod<T>::value) * 1000 +
|
||||
std::is_floating_point<T>::value * 50 + sizeof(T))>;
|
||||
|
||||
template <class T, class U>
|
||||
struct common_storage_impl;
|
||||
|
||||
template <class T, class U>
|
||||
struct common_storage_impl<storage_adaptor<T>, storage_adaptor<U>> {
|
||||
using type =
|
||||
mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
|
||||
type_score<typename storage_adaptor<U>::value_type>::value),
|
||||
storage_adaptor<T>, storage_adaptor<U>>;
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct common_storage_impl<storage_adaptor<T>, unlimited_storage<A>> {
|
||||
using type =
|
||||
mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
|
||||
type_score<typename unlimited_storage<A>::value_type>::value),
|
||||
storage_adaptor<T>, unlimited_storage<A>>;
|
||||
};
|
||||
|
||||
template <class C, class A>
|
||||
struct common_storage_impl<unlimited_storage<A>, storage_adaptor<C>>
|
||||
: common_storage_impl<storage_adaptor<C>, unlimited_storage<A>> {};
|
||||
|
||||
template <class A1, class A2>
|
||||
struct common_storage_impl<unlimited_storage<A1>, unlimited_storage<A2>> {
|
||||
using type = unlimited_storage<A1>;
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
using common_storage = typename common_storage_impl<A, B>::type;
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
74
macx64/include/boost/histogram/detail/compressed_pair.hpp
Normal file
74
macx64/include/boost/histogram/detail/compressed_pair.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <typename T1, typename T2, bool B>
|
||||
class compressed_pair_impl;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class compressed_pair_impl<T1, T2, true> : protected T2 {
|
||||
public:
|
||||
template <typename U1, typename U2>
|
||||
compressed_pair_impl(U1&& u1, U2&& u2)
|
||||
: T2(std::forward<U2>(u2)), first_(std::forward<U1>(u1)) {}
|
||||
template <typename U1>
|
||||
compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
|
||||
compressed_pair_impl() = default;
|
||||
|
||||
T1& first() { return first_; }
|
||||
T2& second() { return static_cast<T2&>(*this); }
|
||||
const T1& first() const { return first_; }
|
||||
const T2& second() const { return static_cast<const T2&>(*this); }
|
||||
|
||||
private:
|
||||
T1 first_;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class compressed_pair_impl<T1, T2, false> {
|
||||
public:
|
||||
template <typename U1, typename U2>
|
||||
compressed_pair_impl(U1&& u1, U2&& u2)
|
||||
: first_(std::forward<U1>(u1)), second_(std::forward<U2>(u2)) {}
|
||||
template <typename U1>
|
||||
compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
|
||||
compressed_pair_impl() = default;
|
||||
|
||||
T1& first() { return first_; }
|
||||
T2& second() { return second_; }
|
||||
const T1& first() const { return first_; }
|
||||
const T2& second() const { return second_; }
|
||||
|
||||
private:
|
||||
T1 first_;
|
||||
T2 second_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
void swap(compressed_pair_impl<Ts...>& a, compressed_pair_impl<Ts...>& b) {
|
||||
using std::swap;
|
||||
swap(a.first(), b.first());
|
||||
swap(a.second(), b.second());
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
using compressed_pair =
|
||||
compressed_pair_impl<T1, T2, (!std::is_final<T2>::value && std::is_empty<T2>::value)>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
337
macx64/include/boost/histogram/detail/linearize.hpp
Normal file
337
macx64/include/boost/histogram/detail/linearize.hpp
Normal file
@@ -0,0 +1,337 @@
|
||||
// Copyright 2015-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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/integral.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct is_accumulator_set : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
using has_underflow =
|
||||
decltype(axis::traits::static_options<T>::test(axis::option::underflow));
|
||||
|
||||
template <class T>
|
||||
struct is_growing
|
||||
: decltype(axis::traits::static_options<T>::test(axis::option::growth)) {};
|
||||
|
||||
template <class... Ts>
|
||||
struct is_growing<std::tuple<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
|
||||
|
||||
template <class... Ts>
|
||||
struct is_growing<axis::variant<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
|
||||
|
||||
template <class T>
|
||||
using has_growing_axis =
|
||||
mp11::mp_if<is_vector_like<T>, is_growing<mp11::mp_first<T>>, is_growing<T>>;
|
||||
|
||||
/// Index with an invalid state
|
||||
struct optional_index {
|
||||
std::size_t idx = 0;
|
||||
std::size_t stride = 1;
|
||||
operator bool() const { return stride > 0; }
|
||||
std::size_t operator*() const { return idx; }
|
||||
};
|
||||
|
||||
inline void linearize(optional_index& out, const axis::index_type extent,
|
||||
const axis::index_type j) noexcept {
|
||||
// j is internal index shifted by +1 if axis has underflow bin
|
||||
out.idx += j * out.stride;
|
||||
// set stride to 0, if j is invalid
|
||||
out.stride *= (0 <= j && j < extent) * extent;
|
||||
}
|
||||
|
||||
// for non-growing axis
|
||||
template <class Axis, class Value>
|
||||
void linearize_value(optional_index& o, const Axis& a, const Value& v) {
|
||||
using B = decltype(axis::traits::static_options<Axis>::test(axis::option::underflow));
|
||||
const auto j = axis::traits::index(a, v) + B::value;
|
||||
linearize(o, axis::traits::extent(a), j);
|
||||
}
|
||||
|
||||
// for variant that does not contain any growing axis
|
||||
template <class... Ts, class Value>
|
||||
void linearize_value(optional_index& o, const axis::variant<Ts...>& a, const Value& v) {
|
||||
axis::visit([&o, &v](const auto& a) { linearize_value(o, a, v); }, a);
|
||||
}
|
||||
|
||||
// for growing axis
|
||||
template <class Axis, class Value>
|
||||
void linearize_value(optional_index& o, axis::index_type& s, Axis& a, const Value& v) {
|
||||
axis::index_type j;
|
||||
std::tie(j, s) = axis::traits::update(a, v);
|
||||
j += has_underflow<Axis>::value;
|
||||
linearize(o, axis::traits::extent(a), j);
|
||||
}
|
||||
|
||||
// for variant which contains at least one growing axis
|
||||
template <class... Ts, class Value>
|
||||
void linearize_value(optional_index& o, axis::index_type& s, axis::variant<Ts...>& a,
|
||||
const Value& v) {
|
||||
axis::visit([&o, &s, &v](auto&& a) { linearize_value(o, s, a, v); }, a);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void linearize_index(optional_index& out, const A& axis, const axis::index_type j) {
|
||||
// A may be axis or variant, cannot use static option detection here
|
||||
const auto opt = axis::traits::options(axis);
|
||||
const auto shift = opt & axis::option::underflow ? 1 : 0;
|
||||
const auto n = axis.size() + (opt & axis::option::overflow ? 1 : 0);
|
||||
linearize(out, n + shift, j + shift);
|
||||
}
|
||||
|
||||
template <class S, class A, class T>
|
||||
void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
bool update_needed = false;
|
||||
auto sit = shifts;
|
||||
for_each_axis(axes, [&](const auto&) { update_needed |= (*sit++ != 0); });
|
||||
if (!update_needed) return;
|
||||
struct item {
|
||||
axis::index_type idx, old_extent;
|
||||
std::size_t new_stride;
|
||||
} data[buffer_size<A>::value];
|
||||
sit = shifts;
|
||||
auto dit = data;
|
||||
std::size_t s = 1;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
const auto n = axis::traits::extent(a);
|
||||
*dit++ = {0, n - std::abs(*sit++), s};
|
||||
s *= n;
|
||||
});
|
||||
auto new_storage = make_default(storage);
|
||||
new_storage.reset(detail::bincount(axes));
|
||||
const auto dlast = data + get_size(axes) - 1;
|
||||
for (const auto& x : storage) {
|
||||
auto ns = new_storage.begin();
|
||||
sit = shifts;
|
||||
dit = data;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
if (opt::test(axis::option::underflow)) {
|
||||
if (dit->idx == 0) {
|
||||
// axis has underflow and we are in the underflow bin:
|
||||
// keep storage pointer unchanged
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (opt::test(axis::option::overflow)) {
|
||||
if (dit->idx == dit->old_extent - 1) {
|
||||
// axis has overflow and we are in the overflow bin:
|
||||
// move storage pointer to corresponding overflow bin position
|
||||
ns += (axis::traits::extent(a) - 1) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// we are in a normal bin:
|
||||
// move storage pointer to index position, apply positive shifts
|
||||
ns += (dit->idx + std::max(*sit, 0)) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
});
|
||||
// assign old value to new location
|
||||
*ns = x;
|
||||
// advance multi-dimensional index
|
||||
dit = data;
|
||||
++dit->idx;
|
||||
while (dit != dlast && dit->idx == dit->old_extent) {
|
||||
dit->idx = 0;
|
||||
++(++dit)->idx;
|
||||
}
|
||||
}
|
||||
storage = std::move(new_storage);
|
||||
}
|
||||
|
||||
// special case: if histogram::operator()(tuple(1, 2)) is called on 1d histogram
|
||||
// with axis that accepts 2d tuple, this should not fail
|
||||
// - solution is to forward tuples of size > 1 directly to axis for 1d
|
||||
// histograms
|
||||
// - has nice side-effect of making histogram::operator(1, 2) work as well
|
||||
// - cannot detect call signature of axis at compile-time in all configurations
|
||||
// (axis::variant provides generic call interface and hides concrete
|
||||
// interface), so we throw at runtime if incompatible argument is passed (e.g.
|
||||
// 3d tuple)
|
||||
// histogram has only non-growing axes
|
||||
template <unsigned I, unsigned N, class S, class T, class U>
|
||||
optional_index args_to_index(std::false_type, S&, const T& axes, const U& args) {
|
||||
optional_index idx;
|
||||
const auto rank = get_size(axes);
|
||||
if (rank == 1 && N > 1)
|
||||
linearize_value(idx, axis_get<0>(axes), tuple_slice<I, N>(args));
|
||||
else {
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
// histogram has growing axes
|
||||
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;
|
||||
axis::index_type shifts[buffer_size<T>::value];
|
||||
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));
|
||||
else {
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
maybe_replace_storage(storage, axes, shifts);
|
||||
return idx;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
constexpr auto weight_sample_indices() {
|
||||
if (is_weight<U>::value) return std::make_pair(0, -1);
|
||||
if (is_sample<U>::value) return std::make_pair(-1, 0);
|
||||
return std::make_pair(-1, -1);
|
||||
}
|
||||
|
||||
template <typename U0, typename U1, typename... Us>
|
||||
constexpr auto weight_sample_indices() {
|
||||
using L = mp11::mp_list<U0, U1, Us...>;
|
||||
const int n = sizeof...(Us) + 1;
|
||||
if (is_weight<mp11::mp_at_c<L, 0>>::value) {
|
||||
if (is_sample<mp11::mp_at_c<L, 1>>::value) return std::make_pair(0, 1);
|
||||
if (is_sample<mp11::mp_at_c<L, n>>::value) return std::make_pair(0, n);
|
||||
return std::make_pair(0, -1);
|
||||
}
|
||||
if (is_sample<mp11::mp_at_c<L, 0>>::value) {
|
||||
if (is_weight<mp11::mp_at_c<L, 1>>::value) return std::make_pair(1, 0);
|
||||
if (is_weight<mp11::mp_at_c<L, n>>::value) return std::make_pair(n, 0);
|
||||
return std::make_pair(-1, 0);
|
||||
}
|
||||
if (is_weight<mp11::mp_at_c<L, n>>::value) {
|
||||
// 0, n already covered
|
||||
if (is_sample<mp11::mp_at_c<L, (n - 1)>>::value) return std::make_pair(n, n - 1);
|
||||
return std::make_pair(n, -1);
|
||||
}
|
||||
if (is_sample<mp11::mp_at_c<L, n>>::value) {
|
||||
// n, 0 already covered
|
||||
if (is_weight<mp11::mp_at_c<L, (n - 1)>>::value) return std::make_pair(n - 1, n);
|
||||
return std::make_pair(-1, n);
|
||||
}
|
||||
return std::make_pair(-1, -1);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void fill_storage(mp11::mp_int<-1>, mp11::mp_int<-1>, T&& t, U&&) {
|
||||
static_if<is_incrementable<remove_cvref_t<T>>>(
|
||||
[](auto&& t) { ++t; }, [](auto&& t) { t(); }, std::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class IW, class T, class U>
|
||||
void fill_storage(IW, mp11::mp_int<-1>, T&& t, U&& args) {
|
||||
static_if<is_incrementable<remove_cvref_t<T>>>(
|
||||
[](auto&& t, const auto& w) { t += w; },
|
||||
[](auto&& t, const auto& w) {
|
||||
#ifdef BOOST_HISTOGRAM_WITH_ACCUMULATORS_SUPPORT
|
||||
static_if<is_accumulator_set<remove_cvref_t<T>>>(
|
||||
[w](auto&& t) { t(::boost::accumulators::weight = w); },
|
||||
[w](auto&& t) { t(w); }, t);
|
||||
#else
|
||||
t(w);
|
||||
#endif
|
||||
},
|
||||
std::forward<T>(t), std::get<IW::value>(args).value);
|
||||
}
|
||||
|
||||
template <class IS, class T, class U>
|
||||
void fill_storage(mp11::mp_int<-1>, IS, T&& t, U&& args) {
|
||||
mp11::tuple_apply([&t](auto&&... args) { t(args...); },
|
||||
std::get<IS::value>(args).value);
|
||||
}
|
||||
|
||||
template <class IW, class IS, class T, class U>
|
||||
void fill_storage(IW, IS, T&& t, U&& args) {
|
||||
mp11::tuple_apply(
|
||||
[&](auto&&... args2) { t(std::get<IW::value>(args).value, args2...); },
|
||||
std::get<IS::value>(args).value);
|
||||
}
|
||||
|
||||
template <class S, class A, class... Us>
|
||||
auto fill(S& storage, A& axes, const std::tuple<Us...>& args) {
|
||||
constexpr auto iws = weight_sample_indices<Us...>();
|
||||
constexpr unsigned n = sizeof...(Us) - (iws.first > -1) - (iws.second > -1);
|
||||
constexpr unsigned i = (iws.first == 0 || iws.second == 0)
|
||||
? (iws.first == 1 || iws.second == 1 ? 2 : 1)
|
||||
: 0;
|
||||
optional_index idx = args_to_index<i, n>(has_growing_axis<A>(), storage, axes, args);
|
||||
if (idx) {
|
||||
fill_storage(mp11::mp_int<iws.first>(), mp11::mp_int<iws.second>(), storage[*idx],
|
||||
args);
|
||||
return storage.begin() + *idx;
|
||||
}
|
||||
return storage.end();
|
||||
}
|
||||
|
||||
template <typename A, typename... Us>
|
||||
optional_index at(const A& axes, const std::tuple<Us...>& args) {
|
||||
if (get_size(axes) != sizeof...(Us))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
|
||||
optional_index idx;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>([&](auto I) {
|
||||
// axes_get works with static and dynamic axes
|
||||
linearize_index(idx, axis_get<I>(axes),
|
||||
static_cast<axis::index_type>(std::get<I>(args)));
|
||||
});
|
||||
return idx;
|
||||
}
|
||||
|
||||
template <typename A, typename U>
|
||||
optional_index at(const A& axes, const U& args) {
|
||||
if (get_size(axes) != get_size(args))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
|
||||
optional_index idx;
|
||||
using std::begin;
|
||||
auto it = begin(args);
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
linearize_index(idx, a, static_cast<axis::index_type>(*it++));
|
||||
});
|
||||
return idx;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
436
macx64/include/boost/histogram/detail/meta.hpp
Normal file
436
macx64/include/boost/histogram/detail/meta.hpp
Normal file
@@ -0,0 +1,436 @@
|
||||
// Copyright 2015-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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_META_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_META_HPP
|
||||
|
||||
/* Most of the histogram code is generic and works for any number of axes. Buffers with a
|
||||
* fixed maximum capacity are used in some places, which have a size equal to the rank of
|
||||
* a histogram. The buffers are statically allocated to improve performance, which means
|
||||
* that they need a preset maximum capacity. 32 seems like a safe upper limit for the rank
|
||||
* (you can nevertheless increase it here if necessary): the simplest non-trivial axis has
|
||||
* 2 bins; even if counters are used which need only a byte of storage per bin, this still
|
||||
* corresponds to 4 GB of storage.
|
||||
*/
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_AXES_LIMIT
|
||||
#define BOOST_HISTOGRAM_DETAIL_AXES_LIMIT 32
|
||||
#endif
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnoexcept-type"
|
||||
#endif
|
||||
#include <boost/callable_traits/args.hpp>
|
||||
#include <boost/callable_traits/return_type.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#include <array>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/integer_sequence.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
template <class T, class U>
|
||||
using convert_integer = mp11::mp_if<std::is_integral<remove_cvref_t<T>>, U, T>;
|
||||
|
||||
// to be replaced by official version from mp11
|
||||
template <class E, template <class...> class F, class... Ts>
|
||||
using mp_eval_or = mp11::mp_eval_if_c<!(mp11::mp_valid<F, Ts...>::value), E, F, Ts...>;
|
||||
|
||||
template <class T1, class T2>
|
||||
using copy_qualifiers = mp11::mp_if<
|
||||
std::is_rvalue_reference<T1>, T2&&,
|
||||
mp11::mp_if<std::is_lvalue_reference<T1>,
|
||||
mp11::mp_if<std::is_const<typename std::remove_reference<T1>::type>,
|
||||
const T2&, T2&>,
|
||||
mp11::mp_if<std::is_const<T1>, const T2, T2>>>;
|
||||
|
||||
template <class L>
|
||||
using mp_last = mp11::mp_at_c<L, (mp11::mp_size<L>::value - 1)>;
|
||||
|
||||
template <class T, class Args = boost::callable_traits::args_t<T>>
|
||||
using args_type =
|
||||
mp11::mp_if<std::is_member_function_pointer<T>, mp11::mp_pop_front<Args>, Args>;
|
||||
|
||||
template <class T, std::size_t N = 0>
|
||||
using arg_type = typename mp11::mp_at_c<args_type<T>, N>;
|
||||
|
||||
template <class T>
|
||||
using return_type = typename boost::callable_traits::return_type<T>::type;
|
||||
|
||||
template <class F, class V,
|
||||
class T = copy_qualifiers<V, mp11::mp_first<remove_cvref_t<V>>>>
|
||||
using visitor_return_type = decltype(std::declval<F>()(std::declval<T>()));
|
||||
|
||||
template <bool B, typename T, typename F, typename... Ts>
|
||||
constexpr decltype(auto) static_if_c(T&& t, F&& f, Ts&&... ts) {
|
||||
return std::get<(B ? 0 : 1)>(std::forward_as_tuple(
|
||||
std::forward<T>(t), std::forward<F>(f)))(std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <typename B, typename... Ts>
|
||||
constexpr decltype(auto) static_if(Ts&&... ts) {
|
||||
return static_if_c<B::value>(std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T lowest() {
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr double lowest() {
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr float lowest() {
|
||||
return -std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T highest() {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr double highest() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr float highest() {
|
||||
return std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
template <std::size_t I, class T, std::size_t... N>
|
||||
decltype(auto) tuple_slice_impl(T&& t, mp11::index_sequence<N...>) {
|
||||
return std::forward_as_tuple(std::get<(N + I)>(std::forward<T>(t))...);
|
||||
}
|
||||
|
||||
template <std::size_t I, std::size_t N, class T>
|
||||
decltype(auto) tuple_slice(T&& t) {
|
||||
static_assert(I + N <= mp11::mp_size<remove_cvref_t<T>>::value,
|
||||
"I and N must describe a slice");
|
||||
return tuple_slice_impl<I>(std::forward<T>(t), mp11::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
#define BOOST_HISTOGRAM_DETECT(name, cond) \
|
||||
template <class T, class = decltype(cond)> \
|
||||
struct name##_impl {}; \
|
||||
template <class T> \
|
||||
using name = typename mp11::mp_valid<name##_impl, T>
|
||||
|
||||
#define BOOST_HISTOGRAM_DETECT_BINARY(name, cond) \
|
||||
template <class T, class U, class = decltype(cond)> \
|
||||
struct name##_impl {}; \
|
||||
template <class T, class U = T> \
|
||||
using name = typename mp11::mp_valid<name##_impl, T, U>
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_metadata, (std::declval<T&>().metadata()));
|
||||
|
||||
// resize has two overloads, trying to get pmf in this case always fails
|
||||
BOOST_HISTOGRAM_DETECT(has_method_resize, (std::declval<T&>().resize(0)));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_size, &T::size);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_clear, &T::clear);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_lower, &T::lower);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_value, &T::value);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_update, (&T::update));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_reset, (std::declval<T>().reset(0)));
|
||||
|
||||
template <typename T>
|
||||
using get_value_method_return_type_impl = decltype(std::declval<T&>().value(0));
|
||||
|
||||
template <typename T, typename R>
|
||||
using has_method_value_with_convertible_return_type =
|
||||
typename std::is_convertible<mp_eval_or<void, get_value_method_return_type_impl, T>,
|
||||
R>::type;
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_options, (&T::options));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_allocator, &T::get_allocator);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_indexable, (std::declval<T&>()[0]));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_transform, (&T::forward, &T::inverse));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_indexable_container,
|
||||
(std::declval<T>()[0], &T::size, std::begin(std::declval<T>()),
|
||||
std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_vector_like,
|
||||
(std::declval<T>()[0], &T::size, std::declval<T>().resize(0),
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_array_like,
|
||||
(std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_map_like,
|
||||
(std::declval<typename T::key_type>(),
|
||||
std::declval<typename T::mapped_type>(),
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
// ok: is_axis is false for axis::variant, operator() is templated
|
||||
BOOST_HISTOGRAM_DETECT(is_axis, (&T::size, &T::index));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_iterable,
|
||||
(std::begin(std::declval<T&>()), std::end(std::declval<T&>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_iterator,
|
||||
(typename std::iterator_traits<T>::iterator_category()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_streamable,
|
||||
(std::declval<std::ostream&>() << std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_incrementable, (++std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_operator_preincrement, (++std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_equal,
|
||||
(std::declval<const T&>() == std::declval<const U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_radd,
|
||||
(std::declval<T&>() += std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rsub,
|
||||
(std::declval<T&>() -= std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rmul,
|
||||
(std::declval<T&>() *= std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rdiv,
|
||||
(std::declval<T&>() /= std::declval<U&>()));
|
||||
|
||||
template <typename T>
|
||||
using is_storage =
|
||||
mp11::mp_bool<(is_indexable_container<T>::value && has_method_reset<T>::value)>;
|
||||
|
||||
template <typename T>
|
||||
struct is_tuple_impl : std::false_type {};
|
||||
|
||||
template <typename... Ts>
|
||||
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_tuple = typename is_tuple_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct is_axis_variant_impl : std::false_type {};
|
||||
|
||||
template <typename... Ts>
|
||||
struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_axis_variant = typename is_axis_variant_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_axis_variant =
|
||||
mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_any_axis =
|
||||
mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_weight_impl : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_weight_impl<weight_type<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_weight = is_weight_impl<remove_cvref_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_sample_impl : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_sample_impl<sample_type<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_sample = is_sample_impl<remove_cvref_t<T>>;
|
||||
|
||||
// poor-mans concept checks
|
||||
template <class T, class = std::enable_if_t<is_iterator<remove_cvref_t<T>>::value>>
|
||||
struct requires_iterator {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_iterable<remove_cvref_t<T>>::value>>
|
||||
struct requires_iterable {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_axis {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_any_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_any_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_axis_variant<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_axis_variant {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_any_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_any_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_any_axis<mp11::mp_first<remove_cvref_t<T>>>::value>>
|
||||
struct requires_axes {};
|
||||
|
||||
template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
|
||||
struct requires_convertible {};
|
||||
|
||||
template <class T>
|
||||
auto make_default(const T& t) {
|
||||
return static_if<has_allocator<T>>([](const auto& t) { return T(t.get_allocator()); },
|
||||
[](const auto&) { return T(); }, t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using tuple_size_t = typename std::tuple_size<T>::type;
|
||||
|
||||
template <class T>
|
||||
constexpr std::size_t get_size_impl(std::true_type, const T&) noexcept {
|
||||
return std::tuple_size<T>::value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t get_size_impl(std::false_type, const T& t) noexcept {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return static_cast<std::size_t>(std::distance(begin(t), end(t)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t get_size(const T& t) noexcept {
|
||||
return get_size_impl(mp11::mp_valid<tuple_size_t, T>(), t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using buffer_size =
|
||||
mp_eval_or<std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>,
|
||||
tuple_size_t, T>;
|
||||
|
||||
template <class T, std::size_t N>
|
||||
class sub_array : public std::array<T, N> {
|
||||
public:
|
||||
explicit sub_array(std::size_t s) : size_(s) {}
|
||||
sub_array(std::size_t s, T value) : size_(s) { std::array<T, N>::fill(value); }
|
||||
|
||||
// need to override both versions of std::array
|
||||
auto end() noexcept { return std::array<T, N>::begin() + size_; }
|
||||
auto end() const noexcept { return std::array<T, N>::begin() + size_; }
|
||||
|
||||
auto size() const noexcept { return size_; }
|
||||
|
||||
private:
|
||||
std::size_t size_ = N;
|
||||
};
|
||||
|
||||
template <class U, class T>
|
||||
using stack_buffer = sub_array<U, buffer_size<T>::value>;
|
||||
|
||||
template <class U, class T, class... Ts>
|
||||
auto make_stack_buffer(const T& t, Ts&&... ts) {
|
||||
return stack_buffer<U, T>(get_size(t), std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr bool relaxed_equal(const T& a, const T& b) noexcept {
|
||||
return static_if<has_operator_equal<T>>(
|
||||
[](const auto& a, const auto& b) { return a == b; },
|
||||
[](const auto&, const auto&) { return true; }, a, b);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using get_scale_type_helper = typename T::value_type;
|
||||
|
||||
template <class T>
|
||||
using get_scale_type = mp_eval_or<T, detail::get_scale_type_helper, T>;
|
||||
|
||||
struct one_unit {};
|
||||
|
||||
template <class T>
|
||||
T operator*(T&& t, const one_unit&) {
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T operator/(T&& t, const one_unit&) {
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using get_unit_type_helper = typename T::unit_type;
|
||||
|
||||
template <class T>
|
||||
using get_unit_type = mp_eval_or<one_unit, detail::get_unit_type_helper, T>;
|
||||
|
||||
template <class T, class R = get_scale_type<T>>
|
||||
R get_scale(const T& t) {
|
||||
return t / get_unit_type<T>();
|
||||
}
|
||||
|
||||
template <class T, class Default>
|
||||
using replace_default = mp11::mp_if<std::is_same<T, use_default>, Default, T>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible_helper =
|
||||
mp11::mp_apply<mp11::mp_all, mp11::mp_transform<std::is_convertible, T, U>>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible = mp_eval_or<std::false_type, is_convertible_helper, T, U>;
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned_impl(std::true_type, const T t) noexcept {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned_impl(std::false_type, const T t) noexcept {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned(const T t) noexcept {
|
||||
return make_unsigned_impl(std::is_integral<T>{}, t);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user