• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_HISTOGRAM_MULTI_INDEX_HPP
8 #define BOOST_HISTOGRAM_MULTI_INDEX_HPP
9 
10 #include <algorithm>
11 #include <boost/histogram/detail/detect.hpp>
12 #include <boost/histogram/detail/nonmember_container_access.hpp>
13 #include <boost/histogram/fwd.hpp>
14 #include <boost/mp11/integer_sequence.hpp>
15 #include <boost/throw_exception.hpp>
16 #include <initializer_list>
17 #include <iterator>
18 #include <stdexcept>
19 #include <tuple>
20 
21 namespace boost {
22 namespace histogram {
23 
24 /** Holder for multiple axis indices.
25 
26   Adapts external iterable, tuple, or explicit list of indices to the same representation.
27  */
28 template <std::size_t Size>
29 struct multi_index {
30   using value_type = axis::index_type;
31   using iterator = value_type*;
32   using const_iterator = const value_type*;
33 
createboost::histogram::multi_index34   static multi_index create(std::size_t s) {
35     if (s != size())
36       BOOST_THROW_EXCEPTION(std::invalid_argument("size does not match static size"));
37     return multi_index(priv_tag{});
38   }
39 
40   template <class... Is>
multi_indexboost::histogram::multi_index41   multi_index(axis::index_type i, Is... is)
42       : multi_index(std::initializer_list<axis::index_type>{
43             i, static_cast<axis::index_type>(is)...}) {}
44 
45   template <class... Is>
multi_indexboost::histogram::multi_index46   multi_index(const std::tuple<axis::index_type, Is...>& is)
47       : multi_index(is, mp11::make_index_sequence<(1 + sizeof...(Is))>{}) {}
48 
49   template <class Iterable, class = detail::requires_iterable<Iterable>>
multi_indexboost::histogram::multi_index50   multi_index(const Iterable& is) {
51     if (detail::size(is) != size())
52       BOOST_THROW_EXCEPTION(std::invalid_argument("no. of axes != no. of indices"));
53     using std::begin;
54     using std::end;
55     std::copy(begin(is), end(is), data_);
56   }
57 
beginboost::histogram::multi_index58   iterator begin() noexcept { return data_; }
endboost::histogram::multi_index59   iterator end() noexcept { return data_ + size(); }
beginboost::histogram::multi_index60   const_iterator begin() const noexcept { return data_; }
endboost::histogram::multi_index61   const_iterator end() const noexcept { return data_ + size(); }
sizeboost::histogram::multi_index62   static constexpr std::size_t size() noexcept { return Size; }
63 
64 private:
65   struct priv_tag {};
66 
multi_indexboost::histogram::multi_index67   multi_index(priv_tag) {}
68 
69   template <class T, std::size_t... Is>
multi_indexboost::histogram::multi_index70   multi_index(const T& is, mp11::index_sequence<Is...>)
71       : multi_index(static_cast<axis::index_type>(std::get<Is>(is))...) {}
72 
73   axis::index_type data_[size()];
74 };
75 
76 template <>
77 struct multi_index<static_cast<std::size_t>(-1)> {
78   using value_type = axis::index_type;
79   using iterator = value_type*;
80   using const_iterator = const value_type*;
81 
createboost::histogram::multi_index82   static multi_index create(std::size_t s) { return multi_index(priv_tag{}, s); }
83 
84   template <class... Is>
multi_indexboost::histogram::multi_index85   multi_index(axis::index_type i, Is... is)
86       : multi_index(std::initializer_list<axis::index_type>{
87             i, static_cast<axis::index_type>(is)...}) {}
88 
89   template <class... Is>
multi_indexboost::histogram::multi_index90   multi_index(const std::tuple<axis::index_type, Is...>& is)
91       : multi_index(is, mp11::make_index_sequence<(1 + sizeof...(Is))>{}) {}
92 
93   template <class Iterable, class = detail::requires_iterable<Iterable>>
multi_indexboost::histogram::multi_index94   multi_index(const Iterable& is) : size_(detail::size(is)) {
95     using std::begin;
96     using std::end;
97     std::copy(begin(is), end(is), data_);
98   }
99 
beginboost::histogram::multi_index100   iterator begin() noexcept { return data_; }
endboost::histogram::multi_index101   iterator end() noexcept { return data_ + size_; }
beginboost::histogram::multi_index102   const_iterator begin() const noexcept { return data_; }
endboost::histogram::multi_index103   const_iterator end() const noexcept { return data_ + size_; }
sizeboost::histogram::multi_index104   std::size_t size() const noexcept { return size_; }
105 
106 private:
107   struct priv_tag {};
108 
multi_indexboost::histogram::multi_index109   multi_index(priv_tag, std::size_t s) : size_(s) {}
110 
111   template <class T, std::size_t... Ns>
multi_indexboost::histogram::multi_index112   multi_index(const T& is, mp11::index_sequence<Ns...>)
113       : multi_index(static_cast<axis::index_type>(std::get<Ns>(is))...) {}
114 
115   std::size_t size_ = 0;
116   static constexpr std::size_t max_size_ = BOOST_HISTOGRAM_DETAIL_AXES_LIMIT;
117   axis::index_type data_[max_size_];
118 };
119 
120 } // namespace histogram
121 } // namespace boost
122 
123 #endif
124