Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RBinIndexMultiDimRange.hxx
Go to the documentation of this file.
1/// \file
2/// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
3/// Feedback is welcome!
4
5#ifndef ROOT_RBinIndexMultiDimRange
6#define ROOT_RBinIndexMultiDimRange
7
8#include "RBinIndex.hxx"
9#include "RBinIndexRange.hxx"
10
11#include <cstddef>
12#include <iterator>
13#include <utility>
14#include <vector>
15
16namespace ROOT {
17namespace Experimental {
18
19/**
20A multidimensional range of bin indices.
21
22The interface allows convenient iteration over multiple RBinIndexRange. The result is available as vector of RBinIndex.
23
24\warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
25Feedback is welcome!
26*/
28 /// The original ranges
29 std::vector<RBinIndexRange> fRanges;
30 /// Whether there is an empty range
31 bool fHasEmptyRange = false;
32
33public:
34 /// Construct an invalid bin index range.
36 /// Construct a multidimensional range of bin indices.
37 RBinIndexMultiDimRange(std::vector<RBinIndexRange> ranges) : fRanges(std::move(ranges))
38 {
39 for (auto &&range : fRanges) {
40 if (range.GetBegin() == range.GetEnd()) {
41 fHasEmptyRange = true;
42 }
43 }
44 }
45
46 const std::vector<RBinIndexRange> &GetRanges() const { return fRanges; }
47
49 {
50 return lhs.fRanges == rhs.fRanges;
51 }
52
54 {
55 return !(lhs == rhs);
56 }
57
58 /// Iterator over RBinIndexMultiDimRange.
61
62 /// The current iterators
63 std::vector<RBinIndexRange::RIterator> fIterators;
64 /// The current bin indices
65 std::vector<RBinIndex> fIndices;
66 /// Pointer to the original RBinIndexMultiDimRange
68
70
71 public:
72 using difference_type = std::ptrdiff_t;
73 using value_type = std::vector<RBinIndex>;
74 using pointer = const std::vector<RBinIndex> *;
75 using reference = const std::vector<RBinIndex> &;
76 using iterator_category = std::input_iterator_tag;
77
78 RIterator() = default;
79
81 {
82 const std::size_t N = fIterators.size();
83 std::size_t j = 0;
84 for (; j < N; j++) {
85 // Reverse iteration order to advance the innermost index first.
86 const std::size_t i = N - 1 - j;
87
88 // Advance this iterator and get the index by dereferencing.
89 // NB: We dereference even if reaching the end. This is fine because we know the implementation of
90 // RBinIndexRange, in the worst case the returned RBinIndex will be invalid.
91 fIterators[i]++;
92 fIndices[i] = *fIterators[i];
93 // If we have not reached the end, we are done (with this loop).
94 if (fIndices[i] != fMultiDimRange->fRanges[i].GetEnd()) {
95 break;
96 }
97 }
98 // If we iterated until j = N, all fIterators and fIndices are at the end.
99 if (j == N) {
100 // Clear fIterators to compare equal to the empty iterator returned by end().
101 fIterators.clear();
102 } else {
103 // Otherwise we need to wrap around the innermost dimensions.
104 for (std::size_t k = 0; k < j; k++) {
105 // Reverse the iteration order as above.
106 const std::size_t i = N - 1 - k;
107 fIterators[i] = fMultiDimRange->fRanges[i].begin();
108 fIndices[i] = *fIterators[i];
109 }
110 }
111 return *this;
112 }
114 {
115 RIterator old = *this;
116 operator++();
117 return old;
118 }
119
120 const std::vector<RBinIndex> &operator*() const { return fIndices; }
121 const std::vector<RBinIndex> *operator->() const { return &fIndices; }
122
123 friend bool operator==(const RIterator &lhs, const RIterator &rhs)
124 {
125 return lhs.fIterators == rhs.fIterators && lhs.fMultiDimRange == rhs.fMultiDimRange;
126 }
127 friend bool operator!=(const RIterator &lhs, const RIterator &rhs) { return !(lhs == rhs); }
128 };
129
131 {
132 RIterator it(*this);
133 // If there is an empty range, return an empty iterator.
134 if (fHasEmptyRange) {
135 return it;
136 }
137
138 for (auto &&range : fRanges) {
139 it.fIterators.push_back(range.begin());
140 it.fIndices.push_back(*it.fIterators.back());
141 }
142 return it;
143 }
144 RIterator end() const { return RIterator(*this); }
145};
146
147} // namespace Experimental
148} // namespace ROOT
149
150#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define N
friend bool operator!=(const RIterator &lhs, const RIterator &rhs)
RIterator(const RBinIndexMultiDimRange &multiDimRange)
std::vector< RBinIndexRange::RIterator > fIterators
The current iterators.
const RBinIndexMultiDimRange * fMultiDimRange
Pointer to the original RBinIndexMultiDimRange.
std::vector< RBinIndex > fIndices
The current bin indices.
friend bool operator==(const RIterator &lhs, const RIterator &rhs)
A multidimensional range of bin indices.
bool fHasEmptyRange
Whether there is an empty range.
RBinIndexMultiDimRange()=default
Construct an invalid bin index range.
std::vector< RBinIndexRange > fRanges
The original ranges.
friend bool operator==(const RBinIndexMultiDimRange &lhs, const RBinIndexMultiDimRange &rhs)
friend bool operator!=(const RBinIndexMultiDimRange &lhs, const RBinIndexMultiDimRange &rhs)
const std::vector< RBinIndexRange > & GetRanges() const
RBinIndexMultiDimRange(std::vector< RBinIndexRange > ranges)
Construct a multidimensional range of bin indices.
const_iterator begin() const