Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-14 10:31:08

0001 /// \file
0002 /// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0003 /// Feedback is welcome!
0004 
0005 #ifndef ROOT_RBinIndexRange
0006 #define ROOT_RBinIndexRange
0007 
0008 #include "RBinIndex.hxx"
0009 
0010 #include <cassert>
0011 #include <cstddef>
0012 #include <iterator>
0013 
0014 namespace ROOT {
0015 namespace Experimental {
0016 
0017 // forward declarations for friend declaration
0018 class RBinIndexRange;
0019 namespace Internal {
0020 static RBinIndexRange CreateBinIndexRange(RBinIndex begin, RBinIndex end, std::size_t nNormalBins);
0021 } // namespace Internal
0022 
0023 /**
0024 A range of bin indices \f$[fBegin, fEnd)\f$.
0025 
0026 The interface allows convenient iteration over RBinIndex. If included, RBinIndex::Underflow() is encountered before the
0027 normal bins and RBinIndex::Overflow() is the last value.
0028 
0029 \code
0030 ROOT::Experimental::RRegularAxis axis(10, 0, 1);
0031 for (auto index : axis.GetNormalRange(2, 5)) {
0032    // Will iterate over [2, 3, 4]
0033 }
0034 for (auto index : axis.GetFullRange()) {
0035    // Will iterate over all bins, starting with the underflow and ending with the overflow bin
0036 }
0037 \endcode
0038 
0039 \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0040 Feedback is welcome!
0041 */
0042 class RBinIndexRange final {
0043    friend RBinIndexRange Internal::CreateBinIndexRange(RBinIndex, RBinIndex, std::size_t);
0044 
0045    /// The begin of the range (inclusive)
0046    RBinIndex fBegin;
0047    /// The end of the range (exclusive)
0048    RBinIndex fEnd;
0049    /// The number of normal bins, after which iteration advances to RBinIndex::Overflow()
0050    std::size_t fNNormalBins = 0;
0051 
0052 public:
0053    /// Construct an invalid bin index range.
0054    RBinIndexRange() = default;
0055 
0056    RBinIndex GetBegin() const { return fBegin; }
0057    RBinIndex GetEnd() const { return fEnd; }
0058    // fNNormalBins is not exposed because it might be confusing for partial ranges.
0059 
0060    friend bool operator==(const RBinIndexRange &lhs, const RBinIndexRange &rhs)
0061    {
0062       return lhs.fBegin == rhs.fBegin && lhs.fEnd == rhs.fEnd && lhs.fNNormalBins == rhs.fNNormalBins;
0063    }
0064 
0065    friend bool operator!=(const RBinIndexRange &lhs, const RBinIndexRange &rhs) { return !(lhs == rhs); }
0066 
0067    /// Iterator over RBinIndex.
0068    class RIterator final {
0069       /// The current bin index
0070       RBinIndex fIndex;
0071       /// The number of normal bins, after which iteration advances to RBinIndex::Overflow()
0072       std::size_t fNNormalBins = 0;
0073 
0074    public:
0075       using difference_type = std::ptrdiff_t;
0076       using value_type = RBinIndex;
0077       using pointer = const RBinIndex *;
0078       using reference = RBinIndex;
0079       using iterator_category = std::input_iterator_tag;
0080 
0081       RIterator() = default;
0082       RIterator(RBinIndex index, std::size_t nNormalBins) : fIndex(index), fNNormalBins(nNormalBins) {}
0083 
0084       RIterator &operator++()
0085       {
0086          if (fIndex.IsUnderflow()) {
0087             fIndex = 0;
0088          } else if (fIndex.IsOverflow()) {
0089             fIndex = RBinIndex();
0090          } else if (fIndex.IsInvalid()) {
0091             // This should never happen! In the worst case, when built with NDEBUG, the iterator stays at Invalid.
0092             assert(0); // GCOVR_EXCL_LINE
0093          } else {
0094             fIndex++;
0095             if (fIndex.GetIndex() == fNNormalBins) {
0096                fIndex = RBinIndex::Overflow();
0097             }
0098          }
0099          return *this;
0100       }
0101       RIterator operator++(int)
0102       {
0103          RIterator old = *this;
0104          operator++();
0105          return old;
0106       }
0107 
0108       RBinIndex operator*() const { return fIndex; }
0109       const RBinIndex *operator->() const { return &fIndex; }
0110 
0111       friend bool operator==(const RIterator &lhs, const RIterator &rhs)
0112       {
0113          return lhs.fIndex == rhs.fIndex && lhs.fNNormalBins == rhs.fNNormalBins;
0114       }
0115       friend bool operator!=(const RIterator &lhs, const RIterator &rhs) { return !(lhs == rhs); }
0116    };
0117 
0118    RIterator begin() const { return RIterator(fBegin, fNNormalBins); }
0119    RIterator end() const { return RIterator(fEnd, fNNormalBins); }
0120 };
0121 
0122 namespace Internal {
0123 
0124 /// %Internal function to create RBinIndexRange.
0125 ///
0126 /// Users are strongly advised to create bin index ranges via the respective axis types, for example with
0127 /// \ref RRegularAxis::GetNormalRange(RBinIndex, RBinIndex) const "RRegularAxis::GetNormalRange(RBinIndex, RBinIndex)"
0128 /// or RRegularAxis::GetFullRange().
0129 ///
0130 /// \param[in] begin the begin of the bin index range (inclusive)
0131 /// \param[in] end the end of the bin index range (exclusive)
0132 /// \param[in] nNormalBins the number of normal bins, after which iteration advances to RBinIndex::Overflow()
0133 static RBinIndexRange CreateBinIndexRange(RBinIndex begin, RBinIndex end, std::size_t nNormalBins)
0134 {
0135    RBinIndexRange range;
0136    range.fBegin = begin;
0137    range.fEnd = end;
0138    range.fNNormalBins = nNormalBins;
0139    return range;
0140 }
0141 
0142 } // namespace Internal
0143 
0144 } // namespace Experimental
0145 } // namespace ROOT
0146 
0147 #endif