ATLAS Offline Software
get_bits.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  */
4 
5 #include "src/get_bits.h"
6 #include "Identifier/Range.h"
7 #include "IdDict/IdDictRegion.h"
8 #include "IdDict/IdDictRange.h"
10 
11 namespace IdDict {
12  typedef std::vector <IdDictRegion*> RV;
13 
14  void
15  compute_bits(const RV& regions, size_t level, const std::string& group) {
16  Range::field ored_field;
17  unsigned int k;
18  for (k = 0; k < regions.size(); ++k) {
19  IdDictRegion* region = regions[k];
20  if (region->fieldSize() <= level) continue;
22  const Range::field thisField = f.field();
23  //on first time, set the original field
24  if (k == 0) ored_field = thisField;
25  //on subsequent iterations, 'or' the new fields with the original
26  else ored_field |= thisField;
27  }
28  //
29  // Now that we have the ored width of all first fields of
30  // all regions, we upgrade the bit width in the corresponding
31  // field implementations.
32  //
33  for (k = 0; k < regions.size(); ++k) {
34  IdDictRegion* region = regions[k];
35  if (region->fieldSize() <= level) continue;
36  // Don't set ored bits for regions outside of group - ok to
37  // calculate with them only
38  if (group != region->m_group) continue;
40  f.set_ored_field(ored_field);
41  }
42  }
43 
44  void
45  get_bits(const RV& regions, size_t level, const std::string& group) {
46  // Invalid call - return
47  if (regions.empty()) return;
48 
49  if (regions.size() == 1) {
50  /*
51  There is only one region (ie one range)
52  therefore the bitsets are unambiguous
53  The bit width of each field implementation is
54  simply the bit width of the corresponding field.
55  */
56  IdDictRegion* region = regions[0];
57  for (size_t k = level; k < region->m_implementation.size(); ++k) {
59  f.set_ored_field(f.field());
60  }
61  return;
62  }
63 
64  size_t k;
65  // Copy the regions provided in the arguments to a local clone.
66  RV mr = regions;
67  // Compute the number of bits needed at this level
75  RV overlapping;
76  RV orig;
77  RV temp;
78  overlapping.reserve(mr.size());
79  orig.reserve(mr.size());
80  temp.reserve(mr.size());
81  for (;; ) {
82  if (mr.empty()) {
83  break;
84  }
85  overlapping.clear();
86  temp.clear();
87  // Find the first non empty Region within the specified group
88  IdDictRegion* reference_region = 0;
89  for (k = 0; k < mr.size(); ++k) {
90  reference_region = mr[k];
91  if (reference_region->m_implementation.size() > level) {
92  if (group == reference_region->m_group) {
93  overlapping.push_back(reference_region);
94  break;
95  } else {
96  temp.push_back(reference_region);
97  }
98  }
99  }
100  // Should be redundant with the mr.size() test above, but put here
101  // to try to avoid coverity warnings that reference_region may be null.
102  if (reference_region == 0) break;
103  if (overlapping.empty()) {
104  break;
105  }
106  // Now really split mr into the two subsets
107  ++k;
108  const IdDictFieldImplementation& f1 = reference_region->m_implementation[level];
109  Range::field ored_field = f1.field();
110  // copy into original test sample, some may have already been
111  // added to temp above.
112  for (; k < mr.size(); ++k) {
113  IdDictRegion* region = mr[k];
114  temp.push_back(region);
115  }
116  bool found_overlap = false;
117  // Compare the reference field at this level to those in the
118  // remaining regions and check for overlap.
119  //
120  // The comparison must be done repeatedly because the overlap
121  // field gets larger and may overlap with previously checked
122  // field of a region.
123  //
124  // By "definition" we require regions in the same group to
125  // overlap to have a uniform bit-allocation for a group.
126  //
127  // For regions outside the current group, the overlap is
128  // allowed for the top level fields with the same names. As
129  // soon as one finds a field with a different name which is in
130  // a region outside the group, this and subsequent fields are
131  // ignored.
132  //
133  do {
134  // copy temp into orig, set overlap to false for this loop over regions
135  orig.clear();
136  orig = temp;
137  temp.clear();
138  found_overlap = false;
139  for (size_t i = 0; i < orig.size(); ++i) {
140  IdDictRegion* region = orig[i];
141  if (region->m_implementation.size() <= level) continue;
142  bool overlap = false;
144  const Range::field& thisField = f.field();
145  // Now expand bits by or'ing them with other regions
146  // at this level, requiring the name to be the same.
147  if (f1.range()->m_field_name == f.range()->m_field_name) overlap = ored_field.overlaps_with(thisField);
148  // Check for either an overlap or force overlap for
149  // regions in the same group
150  if (overlap || (region->m_group == group)) {
151  overlapping.push_back(region);
152  ored_field |= thisField;
153  found_overlap = true;
154  } else {
155  temp.push_back(region);
156  }
157  }
158  } while (found_overlap);
159 
160  // Check overlapping collection - if there are only regions from
161  // the same group, we can safely throw away "temp" the other
162  // collection
163  bool all_within_group = true;
164  bool none_within_group = true;
165  for (size_t i = 0; i < overlapping.size(); ++i) {
166  IdDictRegion* region = overlapping[i];
167  if (group == region->m_group) {
168  none_within_group = false;
169  } else {
170  all_within_group = false;
171  }
172  }
173  // Remove temp is no longer needed
174  if (all_within_group) temp.clear();
175  // Recurse on the remaining fields of the overlapping regions
176  //
177  // Continue only if there are regions still within the current
178  // group
179  if (!none_within_group) {
180  get_bits(overlapping, level + 1, group);
181  }
182  // Continue for the other not-yet-overlapping regions.
183  mr = temp;
184  }
185  }
186 }
IdDictRange.h
IdentifierField::overlaps_with
bool overlaps_with(const IdentifierField &other) const
Check whether two IdentifierFields overlap.
Definition: IdentifierField.cxx:194
IdDict::get_bits
void get_bits(const RV &regions, size_t level, const std::string &group)
Definition: get_bits.cxx:45
Range.h
IdDictRegion::clear
void clear()
Definition: IdDictRegion.cxx:126
IdDictRegion
Definition: IdDictRegion.h:20
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
IdDict
Definition: get_bits.cxx:11
get_bits.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
IdDictRegion::fieldSize
size_t fieldSize() const
Definition: IdDictRegion.cxx:137
hist_file_dump.f
f
Definition: hist_file_dump.py:135
python.update_ci_reference_files.mr
mr
Definition: update_ci_reference_files.py:415
IdDictRegion::m_group
std::string m_group
Definition: IdDictRegion.h:45
IdDict::RV
std::vector< IdDictRegion * > RV
Definition: get_bits.cxx:12
IdDictFieldImplementation.h
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
IdentifierField
This is the individual specification for the range of one ExpandedIdentifier IdentifierField.
Definition: IdentifierField.h:21
IdDictRegion.h
IdDictFieldImplementation
IdDictFieldImplementation is used to capture the specification of a single field of an Identifier.
Definition: IdDictFieldImplementation.h:58
IdDictRegion::m_implementation
std::vector< IdDictFieldImplementation > m_implementation
Definition: IdDictRegion.h:42
fitman.k
k
Definition: fitman.py:528
read_hist_ntuple.f1
f1
Definition: read_hist_ntuple.py:4
IdDict::compute_bits
void compute_bits(const RV &regions, size_t level, const std::string &group)
Compute the OR of all fields at <level>, for the subset of overlapping regions.
Definition: get_bits.cxx:15