ATLAS Offline Software
DetectorDescription/Identifier/src/Range.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 
6 // gcc12 gives false positive warnings from copying boost::small_vector,
7 // as the sort operation in show_all_ids.
8 #if __GNUC__ >= 12
9 # pragma GCC diagnostic ignored "-Wstringop-overread"
10 #endif
11 
12 
13 #include "Identifier/Range.h"
14 #include <algorithm>
15 #include <cstdio>
16 #include <string>
17 #include <vector>
18 
19 #include <limits>
20 #include <iostream>
21 #include <iomanip>
22 #include <stdexcept>
23 #include <cassert>
24 
25 
26 
27 //--------------------------------------------------------------------------
29  if (index >= m_fields.size ()){
30  static const field f;
31  return (f);
32  }
33  return (m_fields[index]);
34 }
35 
36 //-----------------------------------------------
38  if (start < other.fields ()) {
39  field_vector::const_iterator it = other.m_fields.begin ();
40  it += start;
41  m_fields.insert (m_fields.end (), it, other.m_fields.end ());
42  }
43 }
44 
45 Range::Range(const std::string & text):Range(){
46  if (text.empty()) return;
47  std::istringstream in(text);
48  in>>*this;
49 }
50 
51 //-----------------------------------------------
53  // Construct from a root (i.e. add wild card for below)
54  build (root);
55 }
56 
57 //-----------------------------------------------
58 void Range::build (const std::string& text) {
59  if (text.empty()) return;
60  std::istringstream in(text);
61  in>>*this;
62 }
63 
64 //-----------------------------------------------
66  // Construct from a root
67  m_fields.clear ();
68  for (size_type i = 0; i < root.fields (); ++i){
69  m_fields.emplace_back(root[i]);
70  }
71 }
72 
73 
74 
75 //-----------------------------------------------
77  m_fields.emplace_back (value);
78 }
79 
80 //-----------------------------------------------
81 void Range::add (element_type minimum, element_type maximum) {
82  m_fields.emplace_back (minimum, maximum);
83 }
84 
85 
86 
88 void Range::add (const field& f) {
89  m_fields.emplace_back(f);
90 }
91 
93 void Range::add (field&& f) {
94  m_fields.emplace_back(std::move(f));
95 }
96 
98 void Range::add (const Range& subrange) {
99  for (size_t i = 0; i < subrange.fields (); ++i) {
100  const field& f = subrange[i];
101  m_fields.push_back (f);
102  }
103 }
104 
105 void Range::add (Range&& subrange) {
106  if (m_fields.empty())
107  m_fields.swap (subrange.m_fields);
108  else {
109  size_t sz = subrange.m_fields.size();
110  m_fields.reserve (m_fields.size() + sz);
111  for (size_t i = 0; i < sz; ++i) {
112  m_fields.emplace_back (std::move(subrange.m_fields[i]));
113  }
114  }
115 }
116 
117 
118 
119 
120 //-----------------------------------------------
121 void Range::clear () {
122  m_fields.clear ();
123 }
124 
125 //-----------------------------------------------
126 int Range::match (const ExpandedIdentifier& id) const {
127 
128  size_type my_fields = m_fields.size ();
129  const size_type id_fields = id.fields ();
130 
131  // More fields in the range than in the identifier will never match.
132  //if (my_fields > id_fields) return (0);
133 
134  // Allow match for id shorter than range - assume "wildcards" for
135  // missing id fields
136  size_type nfields = (my_fields > id_fields) ? id_fields : my_fields;
137  // Test fields one by one.
138  for (size_type field_number = 0; field_number < nfields; field_number++) {
139  const field& f = m_fields[field_number];
140  if (!f.match (id[field_number])) return (0);
141  }
142  // All conditions match.
143  return (1);
144 }
145 
146 // Accessors
147 
148 //-----------------------------------------------
150  size_type my_fields = m_fields.size ();
152  // Copy fields to result
153  for (size_type field_number = 0; field_number < my_fields; field_number++) {
154  const field& f = m_fields[field_number];
155  // Valued field
156  result << f.get_minimum ();
157  }
158  return (result);
159 }
160 
161 //-----------------------------------------------
163  size_type my_fields = m_fields.size ();
165  // Copy fields to result
166  for (size_type field_number = 0; field_number < my_fields; field_number++) {
167  const field& f = m_fields[field_number];
168  // Normal field
169  result << f.get_maximum ();
170  }
171  return (result);
172 }
173 
175  size_type result = 1;
176  const Range& me = *this;
177  for (size_type i = 0; i < fields (); ++i) {
178  const field& f = me[i];
179  result *= f.get_indices ();
180  }
181  return (result);
182 }
183 
184 
189  size_type result = 0;
190  if (id.fields() != fields()) return (result);
191  const Range& me = *this;
192  // Check if we are above or below this range
193  if (id < minimum()) return 0;
194  if (maximum() < id) return cardinality();
195  // Collect the indices of a match
196  std::vector<size_type> indices(id.fields (), 0);
197  bool is_match = true;
198  size_type level = 0;
199  for (; level < id.fields (); ++level) {
200  const field& f = me[level];
201  // Require all fields to be bounded or enumerated
202  if (f.empty()) return 0;
203  if (f.isEnumerated()) {
204  // Continue testing for a match
205  size_type max = f.get_values().size() - 1;
206  if (f.get_values()[max] < id[level]) {
207  // above max
208  is_match = false;
209  indices[level] = max + 1;
210  } else {
211  for (size_type j = 0; j < f.get_values().size(); ++j) {
212  if (id[level] <= f.get_values()[j]) {
213  if (id[level] != f.get_values()[j]) {
214  // between two values or below first one
215  is_match = false;
216  }
217  indices[level] = j;
218  break;
219  }
220  }
221  }
222  } else {
223  if (f.get_maximum() < id[level]) {
224  // above max
225  is_match = false;
226  indices[level] = f.get_maximum() - f.get_minimum() + 1;
227  } else if (id[level] < f.get_minimum()) {
228  // below min
229  is_match = false;
230  indices[level] = 0;
231  } else {
232  indices[level] = id[level] - f.get_minimum();
233  }
234  }
235  if (!is_match) break;
236  }
237 
238  // Calculate the cardinality
239  if (level < id.fields ()) ++level;
240  for (size_type j = 0; j < level; ++j) {
241  size_type card = indices[j];
242  for (size_type k = j + 1; k < id.fields(); ++k) {
243  const field& f = me[k];
244  card *= f.get_indices();
245  }
246  result += card;
247  }
248  return result;
249 }
250 
251 
258 bool Range::overlaps_with (const Range& other) const {
259  const Range& me = *this;
260  if ((fields () == 0) || (other.fields () == 0)) return (false);
261  for (size_type i = 0; i < std::min (fields (), other.fields ()); ++i){
262  const field& f1 = me[i];
263  const field& f2 = other[i];
264  if (!f1.overlaps_with (f2)) return (false);
265  }
266  return (true);
267 }
268 
269 //-----------------------------------------------
270 void Range::show () const {
271  show (std::cout);
272 }
273 
274 void Range::show (std::ostream& s) const {
275  const Range& me = *this;
276  s << (std::string) me << " (";
277  int allbits = 0;
278  for (size_type i = 0; i < fields (); ++i) {
279  const field& f = me[i];
280  if (i > 0) s << "+";
281  size_type indices = f.get_indices ();
282  int bits = 1;
283  indices--;
284  if (indices > 0) {
285  bits = 0;
286  while (indices > 0){
287  indices /= 2;
288  bits++;
289  }
290  }
291  allbits += bits;
292  s << bits;
293  }
294  s << "=" << allbits << ") ";
295 }
296 
297 //-----------------------------------------------
298 Range::operator std::string () const {
299  std::string result;
300  size_type my_fields = m_fields.size ();
301  if (my_fields == 0) return (result);
302  // print fields one by one.
303  for (size_type field_number = 0; field_number < my_fields; field_number++) {
304  const field& f = m_fields[field_number];
305  if (field_number > 0) result += "/";
306  result += (std::string) f;
307  }
308  return (result);
309 }
310 
311 //-----------------------------------------------
312 bool
314  if (m_fields.size() != other.m_fields.size()) return false;
315  field_vector::const_iterator it1 = m_fields.begin();
316  field_vector::const_iterator it2 = other.m_fields.begin();
317  field_vector::const_iterator last = m_fields.end();
318  for (; it1 != last; ++it1, ++it2) {
319  if ((*it1) != (*it2)) return false;
320  }
321  return (true);
322 }
323 
324 
325 
326 
327 
328 
329 std::ostream &
330 operator << (std::ostream &out, const Range &r){
331  out<<std::string(r);
332  return out;
333 }
334 
335 std::istream &
336 operator >> (std::istream &in, Range &r){
337  r.clear ();
338  for (int c{}; c!=EOF;c=in.peek()){
340  in>>field;
341  r.add(field);
342  if (int c = in.peek();(c == '/') or (c ==' ')){
343  in.ignore();
344  }
345  }
346  return in;
347 }
beamspotman.r
def r
Definition: beamspotman.py:674
Range::clear
void clear()
Modifications.
Definition: DetectorDescription/Identifier/src/Range.cxx:121
fitman.sz
sz
Definition: fitman.py:527
get_generator_info.result
result
Definition: get_generator_info.py:21
Range::operator==
bool operator==(const Range &other) const
Definition: DetectorDescription/Identifier/src/Range.cxx:313
Range::size_type
ExpandedIdentifier::size_type size_type
Definition: DetectorDescription/Identifier/Identifier/Range.h:33
Range::match
int match(const ExpandedIdentifier &id) const
Match an identifier.
Definition: DetectorDescription/Identifier/src/Range.cxx:126
Range::show
void show() const
Definition: DetectorDescription/Identifier/src/Range.cxx:270
index
Definition: index.py:1
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Trk::indices
std::pair< long int, long int > indices
Definition: AlSymMatBase.h:24
Range::maximum
ExpandedIdentifier maximum() const
Definition: DetectorDescription/Identifier/src/Range.cxx:162
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:13
Range.h
skel.it
it
Definition: skel.GENtoEVGEN.py:407
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
ExpandedIdentifier
Definition: DetectorDescription/Identifier/Identifier/ExpandedIdentifier.h:102
athena.value
value
Definition: athena.py:124
sendEI_SPB.root
root
Definition: sendEI_SPB.py:34
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
read_hist_ntuple.f2
f2
Definition: read_hist_ntuple.py:20
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
Range::m_fields
field_vector m_fields
Definition: DetectorDescription/Identifier/Identifier/Range.h:142
Range::minimum
ExpandedIdentifier minimum() const
min and max ExpandedIdentifiers (if they exist, ie.
Definition: DetectorDescription/Identifier/src/Range.cxx:149
operator<<
std::ostream & operator<<(std::ostream &out, const Range &r)
Definition: DetectorDescription/Identifier/src/Range.cxx:330
lumiFormat.i
int i
Definition: lumiFormat.py:85
DetDescrDictionaryDict::it1
std::vector< HWIdentifier >::iterator it1
Definition: DetDescrDictionaryDict.h:17
Range::Range
Range()=default
jobOptions.card
card
Definition: jobOptions.GenevaPy8_Zmumu.py:11
ReadOfcFromCool.nfields
nfields
Definition: ReadOfcFromCool.py:114
hist_file_dump.f
f
Definition: hist_file_dump.py:140
operator>>
std::istream & operator>>(std::istream &in, Range &r)
Definition: DetectorDescription/Identifier/src/Range.cxx:336
Range::fields
size_type fields() const
Definition: DetectorDescription/Identifier/Identifier/Range.h:148
Range::operator[]
const field & operator[](size_type index) const
Access the field elements.
Definition: DetectorDescription/Identifier/src/Range.cxx:28
Range
A Range describes the possible ranges for the field values of an ExpandedIdentifier.
Definition: DetectorDescription/Identifier/Identifier/Range.h:29
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
IdentifierField
This is the individual specification for the range of one ExpandedIdentifier IdentifierField.
Definition: IdentifierField.h:83
Range::overlaps_with
bool overlaps_with(const Range &other) const
Check if two Ranges overlap.
Definition: DetectorDescription/Identifier/src/Range.cxx:258
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
Range::add
void add(element_type value)
Add a required value. (ie. low = high = value)
Definition: DetectorDescription/Identifier/src/Range.cxx:76
makeTransCanvas.text
text
Definition: makeTransCanvas.py:11
Range::cardinality
size_type cardinality() const
Computes a possible cardinality :
Definition: DetectorDescription/Identifier/src/Range.cxx:174
Range::build
void build(const std::string &text)
Build Range from a textual description.
Definition: DetectorDescription/Identifier/src/Range.cxx:58
python.compressB64.c
def c
Definition: compressB64.py:93
Range::element_type
ExpandedIdentifier::element_type element_type
Definition: DetectorDescription/Identifier/Identifier/Range.h:32
fitman.k
k
Definition: fitman.py:528
read_hist_ntuple.f1
f1
Definition: read_hist_ntuple.py:4
Range::cardinalityUpTo
size_type cardinalityUpTo(const ExpandedIdentifier &id) const
Get the cardinality from the beginning up to the given ExpandedIdentifier.
Definition: DetectorDescription/Identifier/src/Range.cxx:188