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