File indexing completed on 2025-12-14 10:31:20
0001
0002
0003
0004
0005 #ifndef ROOT_RRegularAxis
0006 #define ROOT_RRegularAxis
0007
0008 #include "RBinIndex.hxx"
0009 #include "RBinIndexRange.hxx"
0010 #include "RLinearizedIndex.hxx"
0011
0012 #include <cassert>
0013 #include <cstddef>
0014 #include <stdexcept>
0015 #include <string>
0016 #include <utility>
0017
0018 class TBuffer;
0019
0020 namespace ROOT {
0021 namespace Experimental {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class RRegularAxis final {
0038 public:
0039 using ArgumentType = double;
0040
0041 private:
0042
0043 std::size_t fNNormalBins;
0044
0045 double fLow;
0046
0047 double fHigh;
0048
0049 double fInvBinWidth;
0050
0051 bool fEnableFlowBins;
0052
0053 public:
0054
0055
0056
0057
0058
0059 RRegularAxis(std::size_t nNormalBins, std::pair<double, double> interval, bool enableFlowBins = true)
0060 : fNNormalBins(nNormalBins), fLow(interval.first), fHigh(interval.second), fEnableFlowBins(enableFlowBins)
0061 {
0062 if (nNormalBins == 0) {
0063 throw std::invalid_argument("nNormalBins must be > 0");
0064 }
0065 if (fLow >= fHigh) {
0066 std::string msg = "high must be > low, but " + std::to_string(fLow) + " >= " + std::to_string(fHigh);
0067 throw std::invalid_argument(msg);
0068 }
0069 fInvBinWidth = nNormalBins / (fHigh - fLow);
0070 }
0071
0072 std::size_t GetNNormalBins() const { return fNNormalBins; }
0073 std::size_t GetTotalNBins() const { return fEnableFlowBins ? fNNormalBins + 2 : fNNormalBins; }
0074 double GetLow() const { return fLow; }
0075 double GetHigh() const { return fHigh; }
0076 bool HasFlowBins() const { return fEnableFlowBins; }
0077
0078 friend bool operator==(const RRegularAxis &lhs, const RRegularAxis &rhs)
0079 {
0080 return lhs.fNNormalBins == rhs.fNNormalBins && lhs.fLow == rhs.fLow && lhs.fHigh == rhs.fHigh &&
0081 lhs.fEnableFlowBins == rhs.fEnableFlowBins;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 RLinearizedIndex ComputeLinearizedIndex(double x) const
0093 {
0094 bool underflow = x < fLow;
0095
0096 bool overflow = !(x < fHigh);
0097 if (underflow) {
0098 return {fNNormalBins, fEnableFlowBins};
0099 } else if (overflow) {
0100 return {fNNormalBins + 1, fEnableFlowBins};
0101 }
0102
0103 std::size_t bin = (x - fLow) * fInvBinWidth;
0104 return {bin, true};
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114 RLinearizedIndex GetLinearizedIndex(RBinIndex index) const
0115 {
0116 if (index.IsUnderflow()) {
0117 return {fNNormalBins, fEnableFlowBins};
0118 } else if (index.IsOverflow()) {
0119 return {fNNormalBins + 1, fEnableFlowBins};
0120 } else if (index.IsInvalid()) {
0121 return {0, false};
0122 }
0123 assert(index.IsNormal());
0124 std::size_t bin = index.GetIndex();
0125 return {bin, bin < fNNormalBins};
0126 }
0127
0128
0129
0130
0131 RBinIndexRange GetNormalRange() const
0132 {
0133 return Internal::CreateBinIndexRange(RBinIndex(0), RBinIndex(fNNormalBins), 0);
0134 }
0135
0136
0137
0138
0139
0140
0141 RBinIndexRange GetNormalRange(RBinIndex begin, RBinIndex end) const
0142 {
0143 if (!begin.IsNormal()) {
0144 throw std::invalid_argument("begin must be a normal bin");
0145 }
0146 if (begin.GetIndex() >= fNNormalBins) {
0147 throw std::invalid_argument("begin must be inside the axis");
0148 }
0149 if (!end.IsNormal()) {
0150 throw std::invalid_argument("end must be a normal bin");
0151 }
0152 if (end.GetIndex() > fNNormalBins) {
0153 throw std::invalid_argument("end must be inside or past the axis");
0154 }
0155 if (!(end >= begin)) {
0156 throw std::invalid_argument("end must be >= begin");
0157 }
0158 return Internal::CreateBinIndexRange(begin, end, 0);
0159 }
0160
0161
0162
0163
0164
0165
0166 RBinIndexRange GetFullRange() const
0167 {
0168 return fEnableFlowBins ? Internal::CreateBinIndexRange(RBinIndex::Underflow(), RBinIndex(), fNNormalBins)
0169 : GetNormalRange();
0170 }
0171
0172
0173 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RRegularAxis"); }
0174 };
0175
0176 }
0177 }
0178
0179 #endif