File indexing completed on 2026-08-16 09:21:23
0001
0002
0003
0004
0005 #ifndef ROOT_RSliceBinIndexMapper
0006 #define ROOT_RSliceBinIndexMapper
0007
0008 #include "RBinIndex.hxx"
0009 #include "RBinIndexRange.hxx"
0010 #include "RSliceSpec.hxx"
0011
0012 #include <cstdint>
0013 #include <stdexcept>
0014 #include <utility>
0015 #include <vector>
0016
0017 namespace ROOT {
0018 namespace Experimental {
0019 namespace Internal {
0020
0021
0022
0023
0024 class RSliceBinIndexMapper final {
0025
0026 std::vector<RSliceSpec> fSliceSpecs;
0027
0028 std::size_t fMappedDimensionality;
0029
0030 static std::size_t ComputeMappedDimensionality(const std::vector<RSliceSpec> &sliceSpecs)
0031 {
0032 std::size_t dimensionality = 0;
0033 for (auto &&spec : sliceSpecs) {
0034
0035 if (spec.GetOperationSum() == nullptr) {
0036 dimensionality++;
0037 }
0038 }
0039 return dimensionality;
0040 }
0041
0042 public:
0043
0044 explicit RSliceBinIndexMapper(std::vector<RSliceSpec> sliceSpecs)
0045 : fSliceSpecs(std::move(sliceSpecs)), fMappedDimensionality(ComputeMappedDimensionality(fSliceSpecs))
0046 {
0047 if (fSliceSpecs.empty()) {
0048 throw std::invalid_argument("must have at least 1 slice specification");
0049 }
0050 }
0051
0052 const std::vector<RSliceSpec> &GetSliceSpecs() const { return fSliceSpecs; }
0053 std::size_t GetMappedDimensionality() const { return fMappedDimensionality; }
0054
0055
0056
0057
0058
0059
0060 bool Map(const std::vector<RBinIndex> &original, std::vector<RBinIndex> &mapped) const
0061 {
0062 if (original.size() != fSliceSpecs.size()) {
0063 throw std::invalid_argument("invalid number of original indices passed to RSliceBinIndexMapper::Map");
0064 }
0065 if (mapped.size() != fMappedDimensionality) {
0066 throw std::invalid_argument("invalid size of mapped indices passed to RSliceBinIndexMapper::Map");
0067 }
0068
0069 std::size_t mappedPos = 0;
0070 for (std::size_t i = 0; i < original.size(); i++) {
0071 RBinIndex index = original[i];
0072 if (index.IsInvalid()) {
0073 throw std::invalid_argument("invalid bin index passed to RSliceBinIndexMapper::Map");
0074 }
0075
0076 const RSliceSpec &sliceSpec = fSliceSpecs[i];
0077 const auto &range = sliceSpec.GetRange();
0078 bool contained = true;
0079 if (!range.IsInvalid()) {
0080
0081
0082 if (index.IsUnderflow()) {
0083 contained = range.GetBegin().IsUnderflow();
0084 } else if (index.IsOverflow()) {
0085 contained = range.GetEnd().IsInvalid();
0086 } else if (index.IsNormal()) {
0087 const auto &begin = range.GetBegin();
0088 const auto &end = range.GetEnd();
0089 if (begin.IsNormal() && index < begin) {
0090 index = RBinIndex::Underflow();
0091 contained = false;
0092 } else if (end.IsNormal() && index >= end) {
0093 index = RBinIndex::Overflow();
0094 contained = false;
0095 } else if (begin.IsNormal()) {
0096
0097
0098 index -= begin.GetIndex();
0099 assert(!index.IsInvalid());
0100 }
0101 }
0102 }
0103
0104 if (auto *opRebin = sliceSpec.GetOperationRebin()) {
0105 if (index.IsNormal()) {
0106 index = RBinIndex(index.GetIndex() / opRebin->GetNGroup());
0107 }
0108 } else if (sliceSpec.GetOperationSum() != nullptr) {
0109
0110 if (!contained) {
0111 return false;
0112 }
0113
0114 continue;
0115 }
0116
0117 mapped[mappedPos] = index;
0118 mappedPos++;
0119 }
0120
0121
0122 assert(mappedPos == mapped.size());
0123 return true;
0124 }
0125 };
0126
0127 }
0128 }
0129 }
0130
0131 #endif