File indexing completed on 2025-01-30 09:43:48
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_HISTOGRAM_MULTI_INDEX_HPP
0008 #define BOOST_HISTOGRAM_MULTI_INDEX_HPP
0009
0010 #include <algorithm>
0011 #include <boost/histogram/detail/detect.hpp>
0012 #include <boost/histogram/detail/nonmember_container_access.hpp>
0013 #include <boost/histogram/fwd.hpp>
0014 #include <boost/mp11/integer_sequence.hpp>
0015 #include <boost/throw_exception.hpp>
0016 #include <initializer_list>
0017 #include <iterator>
0018 #include <stdexcept>
0019 #include <tuple>
0020
0021 namespace boost {
0022 namespace histogram {
0023
0024
0025
0026
0027
0028 template <std::size_t Size>
0029 struct multi_index {
0030 using value_type = axis::index_type;
0031 using iterator = value_type*;
0032 using const_iterator = const value_type*;
0033
0034 static multi_index create(std::size_t s) {
0035 if (s != size())
0036 BOOST_THROW_EXCEPTION(std::invalid_argument("size does not match static size"));
0037 return multi_index(priv_tag{});
0038 }
0039
0040 template <class... Is>
0041 multi_index(axis::index_type i, Is... is)
0042 : multi_index(std::initializer_list<axis::index_type>{
0043 i, static_cast<axis::index_type>(is)...}) {}
0044
0045 template <class... Is>
0046 multi_index(const std::tuple<axis::index_type, Is...>& is)
0047 : multi_index(is, mp11::make_index_sequence<(1 + sizeof...(Is))>{}) {}
0048
0049 template <class Iterable, class = detail::requires_iterable<Iterable>>
0050 multi_index(const Iterable& is) {
0051 if (detail::size(is) != size())
0052 BOOST_THROW_EXCEPTION(std::invalid_argument("no. of axes != no. of indices"));
0053 using std::begin;
0054 using std::end;
0055 std::copy(begin(is), end(is), data_);
0056 }
0057
0058 iterator begin() noexcept { return data_; }
0059 iterator end() noexcept { return data_ + size(); }
0060 const_iterator begin() const noexcept { return data_; }
0061 const_iterator end() const noexcept { return data_ + size(); }
0062 static constexpr std::size_t size() noexcept { return Size; }
0063
0064 private:
0065 struct priv_tag {};
0066
0067 multi_index(priv_tag) {}
0068
0069 template <class T, std::size_t... Is>
0070 multi_index(const T& is, mp11::index_sequence<Is...>)
0071 : multi_index(static_cast<axis::index_type>(std::get<Is>(is))...) {}
0072
0073 axis::index_type data_[size()];
0074 };
0075
0076 template <>
0077 struct multi_index<static_cast<std::size_t>(-1)> {
0078 using value_type = axis::index_type;
0079 using iterator = value_type*;
0080 using const_iterator = const value_type*;
0081
0082 static multi_index create(std::size_t s) { return multi_index(priv_tag{}, s); }
0083
0084 template <class... Is>
0085 multi_index(axis::index_type i, Is... is)
0086 : multi_index(std::initializer_list<axis::index_type>{
0087 i, static_cast<axis::index_type>(is)...}) {}
0088
0089 template <class... Is>
0090 multi_index(const std::tuple<axis::index_type, Is...>& is)
0091 : multi_index(is, mp11::make_index_sequence<(1 + sizeof...(Is))>{}) {}
0092
0093 template <class Iterable, class = detail::requires_iterable<Iterable>>
0094 multi_index(const Iterable& is) : size_(detail::size(is)) {
0095 using std::begin;
0096 using std::end;
0097 std::copy(begin(is), end(is), data_);
0098 }
0099
0100 iterator begin() noexcept { return data_; }
0101 iterator end() noexcept { return data_ + size_; }
0102 const_iterator begin() const noexcept { return data_; }
0103 const_iterator end() const noexcept { return data_ + size_; }
0104 std::size_t size() const noexcept { return size_; }
0105
0106 private:
0107 struct priv_tag {};
0108
0109 multi_index(priv_tag, std::size_t s) : size_(s) {}
0110
0111 template <class T, std::size_t... Ns>
0112 multi_index(const T& is, mp11::index_sequence<Ns...>)
0113 : multi_index(static_cast<axis::index_type>(std::get<Ns>(is))...) {}
0114
0115 std::size_t size_ = 0;
0116 static constexpr std::size_t max_size_ = BOOST_HISTOGRAM_DETAIL_AXES_LIMIT;
0117 axis::index_type data_[max_size_];
0118 };
0119
0120 }
0121 }
0122
0123 #endif