File indexing completed on 2025-01-18 09:38:12
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
0009
0010 #include <boost/histogram/axis/option.hpp>
0011 #include <boost/histogram/axis/traits.hpp>
0012 #include <boost/histogram/axis/variant.hpp>
0013 #include <boost/histogram/detail/optional_index.hpp>
0014 #include <boost/histogram/fwd.hpp>
0015 #include <boost/histogram/multi_index.hpp>
0016 #include <cassert>
0017
0018 namespace boost {
0019 namespace histogram {
0020 namespace detail {
0021
0022
0023
0024 template <class Opts>
0025 std::size_t linearize(Opts, std::size_t& out, const std::size_t stride,
0026 const axis::index_type size, const axis::index_type idx) {
0027 constexpr bool u = Opts::test(axis::option::underflow);
0028 constexpr bool o = Opts::test(axis::option::overflow);
0029 assert(idx >= (u ? -1 : 0));
0030 assert(idx < (o ? size + 1 : size));
0031 assert(idx >= 0 || static_cast<std::size_t>(-idx * stride) <= out);
0032 out += idx * stride;
0033 return size + u + o;
0034 }
0035
0036
0037
0038 template <class Opts>
0039 std::size_t linearize(Opts, optional_index& out, const std::size_t stride,
0040 const axis::index_type size, const axis::index_type idx) {
0041 constexpr bool u = Opts::test(axis::option::underflow);
0042 constexpr bool o = Opts::test(axis::option::overflow);
0043 assert(idx >= -1);
0044 assert(idx < size + 1);
0045 const bool is_valid = (u || idx >= 0) && (o || idx < size);
0046 if (is_valid)
0047 out += idx * stride;
0048 else
0049 out = invalid_index;
0050 return size + u + o;
0051 }
0052
0053 template <class Index, class Axis, class Value>
0054 std::size_t linearize(Index& out, const std::size_t stride, const Axis& ax,
0055 const Value& v) {
0056
0057 constexpr auto opts = axis::traits::get_options<Axis>{} &
0058 (axis::option::underflow | axis::option::overflow);
0059 return linearize(opts, out, stride, ax.size(), axis::traits::index(ax, v));
0060 }
0061
0062
0063
0064
0065
0066
0067
0068 template <class Index, class Axis, class Value>
0069 std::size_t linearize_growth(Index& out, axis::index_type& shift,
0070 const std::size_t stride, Axis& a, const Value& v) {
0071 axis::index_type idx;
0072 std::tie(idx, shift) = axis::traits::update(a, v);
0073 constexpr bool u = axis::traits::get_options<Axis>::test(axis::option::underflow);
0074 if (u) ++idx;
0075 if (std::is_same<Index, std::size_t>::value) {
0076 assert(idx < axis::traits::extent(a));
0077 out += idx * stride;
0078 } else {
0079 if (0 <= idx && idx < axis::traits::extent(a))
0080 out += idx * stride;
0081 else
0082 out = invalid_index;
0083 }
0084 return axis::traits::extent(a);
0085 }
0086
0087
0088 template <class A>
0089 std::size_t linearize_index(optional_index& out, const std::size_t stride, const A& ax,
0090 const axis::index_type idx) noexcept {
0091 const auto opt = axis::traits::get_options<A>();
0092 const axis::index_type begin = opt & axis::option::underflow ? -1 : 0;
0093 const axis::index_type end = opt & axis::option::overflow ? ax.size() + 1 : ax.size();
0094 const axis::index_type extent = end - begin;
0095
0096 if (begin <= idx && idx < end)
0097 out += (idx - begin) * stride;
0098 else
0099 out = invalid_index;
0100 return extent;
0101 }
0102
0103 template <class A, std::size_t N>
0104 optional_index linearize_indices(const A& axes, const multi_index<N>& indices) noexcept {
0105 assert(axes_rank(axes) == detail::size(indices));
0106
0107 optional_index idx{0};
0108 auto stride = static_cast<std::size_t>(1);
0109 using std::begin;
0110 auto i = begin(indices);
0111 for_each_axis(axes,
0112 [&](const auto& a) { stride *= linearize_index(idx, stride, a, *i++); });
0113 return idx;
0114 }
0115
0116 template <class Index, class... Ts, class Value>
0117 std::size_t linearize(Index& o, const std::size_t s, const axis::variant<Ts...>& a,
0118 const Value& v) {
0119 return axis::visit([&o, &s, &v](const auto& a) { return linearize(o, s, a, v); }, a);
0120 }
0121
0122 template <class Index, class... Ts, class Value>
0123 std::size_t linearize_growth(Index& o, axis::index_type& sh, const std::size_t st,
0124 axis::variant<Ts...>& a, const Value& v) {
0125 return axis::visit([&](auto& a) { return linearize_growth(o, sh, st, a, v); }, a);
0126 }
0127
0128 }
0129 }
0130 }
0131
0132 #endif